@cardstack/boxel-cli 0.3.2-unstable.61 → 0.4.0-unstable.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-realms/base/card-api.gts +2 -0
- package/bundled-realms/base/components/cards-grid-layout.gts +24 -2
- package/bundled-realms/base/field-component.gts +16 -4
- package/bundled-realms/base/links-to-editor.gts +27 -3
- package/bundled-realms/base/realm-config.gts +18 -1
- package/bundled-test-harness/assets/adapter-unm-Xq4g.js +2 -0
- package/bundled-test-harness/assets/{add-field-to-card-definition-command-test-DkxmkPH6.js → add-field-to-card-definition-command-test-CCaDu5uP.js} +2 -2
- package/bundled-test-harness/assets/{add-workspace-tMjv_Ar4.js → add-workspace-DBDTvtP2.js} +3 -3
- package/bundled-test-harness/assets/{add-workspace-test-BMKxSlaC.js → add-workspace-test-CE21v7jK.js} +3 -3
- package/bundled-test-harness/assets/{ai-assistant-test-C3LjW9Uz.js → ai-assistant-test-DSyMR0hY.js} +8 -7
- package/bundled-test-harness/assets/{ai-function-generation-test-WqD9vlzP.js → ai-function-generation-test-BkTvuCnq.js} +1 -1
- package/bundled-test-harness/assets/{ai-module-creation-test-CeP1V90-.js → ai-module-creation-test-zY83EN93.js} +3 -3
- package/bundled-test-harness/assets/{aibot-message-CiwsV-h8.js → aibot-message-BfRah4Lm.js} +2 -2
- package/bundled-test-harness/assets/{app-C8fZHSIY.js → app-CPRVydcd.js} +321 -33
- package/bundled-test-harness/assets/{apply-markdown-edit-test-VkN9mVg4.js → apply-markdown-edit-test-CpeCS12T.js} +2 -2
- package/bundled-test-harness/assets/{apply-search-replace-block-test-C4GiLUbz.js → apply-search-replace-block-test-Czoi47xr.js} +1 -1
- package/bundled-test-harness/assets/{auth-service-worker-registration-CGUqW_lr.js → auth-service-worker-registration-C3rAs9Yi.js} +1 -1
- package/bundled-test-harness/assets/{auth-service-worker-test-DjVH_n4v.js → auth-service-worker-test-DTHQyoUg.js} +3 -3
- package/bundled-test-harness/assets/{authed-fetch-test-PT9AWQEk.js → authed-fetch-test-BRqybmXe.js} +2 -2
- package/bundled-test-harness/assets/{avif-image-def-test-BMFnvMFY.js → avif-image-def-test-BVwv4Ahc.js} +1 -1
- package/bundled-test-harness/assets/{basic-test-B5EcLZRP.js → basic-test-Dbky79J2.js} +1 -1
- package/bundled-test-harness/assets/{binary-upload-dedupe-test-BvQVNF95.js → binary-upload-dedupe-test-nnaYqiTh.js} +3 -3
- package/bundled-test-harness/assets/{bot-registration-test-Cy1HY7PT.js → bot-registration-test-zrufhFTo.js} +2 -2
- package/bundled-test-harness/assets/{box-test-BTOPLQ3k.js → box-test-B85wfMJn.js} +1 -1
- package/bundled-test-harness/assets/{brand-guide-attachments-test-C4R_z8N5.js → brand-guide-attachments-test-C8-n-naq.js} +2 -2
- package/bundled-test-harness/assets/{brand-guide-custom-css-test-Me-k86li.js → brand-guide-custom-css-test-B2fmvFp4.js} +2 -2
- package/bundled-test-harness/assets/{brand-logo-mark-field-test-DcCSpYJq.js → brand-logo-mark-field-test-CJ4s6jjd.js} +2 -2
- package/bundled-test-harness/assets/{broken-link-template-test-BRD2BX45.js → broken-link-template-test-BHXrPxQ6.js} +2 -2
- package/bundled-test-harness/assets/{can-read-realm-test-_flXUfS4.js → can-read-realm-test-mHnz9-_s.js} +2 -2
- package/bundled-test-harness/assets/{cancel-indexing-job-test-0JyPszPo.js → cancel-indexing-job-test-Drx2ghoA.js} +2 -2
- package/bundled-test-harness/assets/{card-api-test-BpeMpeQ0.js → card-api-test-C0HrvAuC.js} +3 -3
- package/bundled-test-harness/assets/{card-basics-test-C-UCeun-.js → card-basics-test-CvITmKK-.js} +3 -3
- package/bundled-test-harness/assets/{card-catalog-test-4K3_LE47.js → card-catalog-test-CWkfBRuQ.js} +3 -3
- package/bundled-test-harness/assets/{card-copy-test-BFFsV3G-.js → card-copy-test-Co_MPCIJ.js} +3 -3
- package/bundled-test-harness/assets/{card-def-field-def-relationships-test-CRjFV5pq.js → card-def-field-def-relationships-test-7e-g4qJs.js} +3 -3
- package/bundled-test-harness/assets/{card-def-menu-items-test-DQNnU_0P.js → card-def-menu-items-test-DLO6TEhC.js} +1 -1
- package/bundled-test-harness/assets/{card-delete-test-DOyt5y-x.js → card-delete-test-BcOtJYm4.js} +3 -3
- package/bundled-test-harness/assets/{card-error-detail-DuFoktdn.js → card-error-detail-Q7wtuRcv.js} +2 -2
- package/bundled-test-harness/assets/{card-playground-test-CiESzD5-.js → card-playground-test-DxoIBbjx.js} +3 -3
- package/bundled-test-harness/assets/{card-search-adorn-test-DdTUl5RY.js → card-search-adorn-test-CbsnFvDF.js} +2 -2
- package/bundled-test-harness/assets/{card-search-selection-menu-test-BJFUbgA1.js → card-search-selection-menu-test-CY77b1kz.js} +2 -2
- package/bundled-test-harness/assets/{check-correctness-test-B4E7WXSZ.js → check-correctness-test-D0EYMlP7.js} +2 -2
- package/bundled-test-harness/assets/{check-domain-availability-test-BnmsW2P7.js → check-domain-availability-test-BYAkVLGj.js} +2 -2
- package/bundled-test-harness/assets/{code-patches-test-6Lvfhm1l.js → code-patches-test-BDg35i4X.js} +1 -1
- package/bundled-test-harness/assets/{code-ref-test-BWuTdZ2e.js → code-ref-test-BZGL3teK.js} +1 -1
- package/bundled-test-harness/assets/{code-submode-test-DPzE9tKe.js → code-submode-test-DIiXgCRB.js} +3 -3
- package/bundled-test-harness/assets/{codeblocks-test-MV1tHflj.js → codeblocks-test-CFR0u5-j.js} +3 -3
- package/bundled-test-harness/assets/{codemirror-editor-test-SD3gDmHw.js → codemirror-editor-test-e1Yn_b_1.js} +1 -1
- package/bundled-test-harness/assets/{color-field-test-C_7cf4Z2.js → color-field-test-okcvtdsF.js} +2 -2
- package/bundled-test-harness/assets/{commands-DoigkJc8.js → commands-BOwQjc8N.js} +3 -3
- package/bundled-test-harness/assets/{commands-calling-test-Br4sMoMf.js → commands-calling-test-BETL8EWm.js} +2 -2
- package/bundled-test-harness/assets/{commands-test-71b4Fun5.js → commands-test-BpFjXsiC.js} +3 -3
- package/bundled-test-harness/assets/{commands-test-COT9Ck-6.js → commands-test-QSW7zRvO.js} +2 -2
- package/bundled-test-harness/assets/{components-CBfd9MIo.js → components-DYC4nC4r.js} +184 -184
- package/bundled-test-harness/assets/{components-8vaKSlYm.css → components-DgK6vTbM.css} +17 -14
- package/bundled-test-harness/assets/{computed-test-BbCVTMkD.js → computed-test-C2j8r-e_.js} +2 -2
- package/bundled-test-harness/assets/{container-BVdtw4NT.js → container-DRblzvCW.js} +18 -18
- package/bundled-test-harness/assets/{convert-to-class-name-test-DmF3wUKb.js → convert-to-class-name-test-BiCrnGxA.js} +1 -1
- package/bundled-test-harness/assets/{copy-and-edit-test-1xrTe8p1.js → copy-and-edit-test-DqV_dpu_.js} +1 -1
- package/bundled-test-harness/assets/{copy-card-test-D0rXx03h.js → copy-card-test-B4dNP03f.js} +1 -1
- package/bundled-test-harness/assets/{copy-file-to-realm-test-DxW5PABL.js → copy-file-to-realm-test-oGK9EM0P.js} +1 -1
- package/bundled-test-harness/assets/{copy-source-test-Dy83btnV.js → copy-source-test-GtNFw5fv.js} +2 -2
- package/bundled-test-harness/assets/{create-file-modal-BNJHELMz.js → create-file-modal-Cfvn0u5s.js} +4 -4
- package/bundled-test-harness/assets/{create-file-test-DimDxpRl.js → create-file-test-2WPpTJ5F.js} +1 -1
- package/bundled-test-harness/assets/{create-file-test-COppMhde.js → create-file-test-HxkEMHWL.js} +2 -2
- package/bundled-test-harness/assets/{create-listing-modal-test-D57Altg2.js → create-listing-modal-test-W6LuCzaK.js} +4 -4
- package/bundled-test-harness/assets/{create-listing-pr-request-test-HJmFkx_x.js → create-listing-pr-request-test-2ZRF_IBk.js} +2 -2
- package/bundled-test-harness/assets/{create-spec-test-C-4bkoj3.js → create-spec-test-JVOisAUl.js} +1 -1
- package/bundled-test-harness/assets/{csv-file-def-test-GOmD6Ikx.js → csv-file-def-test-DIVp_7a6.js} +1 -1
- package/bundled-test-harness/assets/{date-time-fields-test-BYn57092.js → date-time-fields-test-BWdrrYdj.js} +2 -2
- package/bundled-test-harness/assets/{debug-message-test-CNzx_IFI.js → debug-message-test-CXVfUuec.js} +3 -3
- package/bundled-test-harness/assets/{diffing-test-PA40XPFB.js → diffing-test-JzXF051K.js} +1 -1
- package/bundled-test-harness/assets/{editor-test-Dg1fTno0.js → editor-test-j9znzFxy.js} +2 -2
- package/bundled-test-harness/assets/{email-field-test-rPWkRvgR.js → email-field-test-D4vZ2Qnc.js} +2 -2
- package/bundled-test-harness/assets/{enum-field-test-DjQ-sjAR.js → enum-field-test-DtZ_sOiA.js} +2 -2
- package/bundled-test-harness/assets/{error-display-test-Cp1vgWSg.js → error-display-test-B6I8CYXw.js} +2 -2
- package/bundled-test-harness/assets/{evaluate-module-test-Bm6adsJS.js → evaluate-module-test-C_F1Y9Az.js} +1 -1
- package/bundled-test-harness/assets/{execute-atomic-operations-test-BAB2vv15.js → execute-atomic-operations-test-D_z5eJ6K.js} +2 -2
- package/bundled-test-harness/assets/{externals-C65aJ_7H.js → externals-DiG6hYU9.js} +2 -2
- package/bundled-test-harness/assets/fallback-banner-live-delete-test-Bv_OBmzY.js +209 -0
- package/bundled-test-harness/assets/{fallback-banner-test-Md-3yTpX.js → fallback-banner-test-DSjH5ank.js} +1 -1
- package/bundled-test-harness/assets/{fallback-banner-test-DpCz2idU.js → fallback-banner-test-TL8jNe4f.js} +3 -3
- package/bundled-test-harness/assets/{fallback-models-test-DcB9u65l.js → fallback-models-test-DEhvKsfY.js} +3 -3
- package/bundled-test-harness/assets/{fetch-card-json-test-CPHdklsi.js → fetch-card-json-test-BPfTOr4N.js} +2 -2
- package/bundled-test-harness/assets/{field-configuration-test-Da5xu3ar.js → field-configuration-test-CH1Kc0iA.js} +2 -2
- package/bundled-test-harness/assets/{field-markdown-domain-test-7aY4gMQ3.js → field-markdown-domain-test-COaJBBzN.js} +2 -2
- package/bundled-test-harness/assets/{field-markdown-primitives-test-B8UurS_m.js → field-markdown-primitives-test-C52WikZw.js} +2 -2
- package/bundled-test-harness/assets/{field-markdown-specialized-test-CHiWEV2t.js → field-markdown-specialized-test-Cmq-3t4u.js} +2 -2
- package/bundled-test-harness/assets/{field-playground-test-DBVHB2_g.js → field-playground-test-DbXri11f.js} +3 -3
- package/bundled-test-harness/assets/{field-support-predicates-test-i8LXzh_P.js → field-support-predicates-test-ni5pZ9sU.js} +1 -1
- package/bundled-test-harness/assets/{field-test-helpers-F8iX3xAt.js → field-test-helpers-BLApZo43.js} +1 -1
- package/bundled-test-harness/assets/{file-DUbLArQi.js → file-D8hnXC1_.js} +8 -2
- package/bundled-test-harness/assets/{file-attachment-test-yfZsKhWQ.js → file-attachment-test-CkL6IaWf.js} +3 -3
- package/bundled-test-harness/assets/{file-chooser-test-JOvGg1N8.js → file-chooser-test-M1rOgltw.js} +2 -2
- package/bundled-test-harness/assets/{file-def-live-reload-test-B_XsrkaB.js → file-def-live-reload-test--L4MvUj5.js} +1 -1
- package/bundled-test-harness/assets/{file-def-menu-items-test-CkZrFXrK.js → file-def-menu-items-test-B_dVulF7.js} +1 -1
- package/bundled-test-harness/assets/{file-def-navigation-test-CyO27adK.js → file-def-navigation-test-B4_pzEXy.js} +1 -1
- package/bundled-test-harness/assets/{file-def-serialization-test-1XrP63F8.js → file-def-serialization-test-IoGIzKST.js} +1 -1
- package/bundled-test-harness/assets/{file-def-test-BJEhQN1c.js → file-def-test-CT8jTLQy.js} +1 -1
- package/bundled-test-harness/assets/{file-tree-test-DQSPDeb2.js → file-tree-test-DQNSRISM.js} +2 -2
- package/bundled-test-harness/assets/{flac-audio-def-test-CeyxsGOr.js → flac-audio-def-test-CEt7tShK.js} +1 -1
- package/bundled-test-harness/assets/{formatted-aibot-message-test-D09eSldQ.js → formatted-aibot-message-test-CNk1lVYO.js} +3 -3
- package/bundled-test-harness/assets/{formatted-user-message-test-DmX95kEo.js → formatted-user-message-test-By3DTUBk.js} +2 -2
- package/bundled-test-harness/assets/{freestyle-test-KaFCs8l2.js → freestyle-test-BOVAHn_7.js} +1 -1
- package/bundled-test-harness/assets/{full-reindex-realm-test-BCUSPZuX.js → full-reindex-realm-test-BQji9QK_.js} +2 -2
- package/bundled-test-harness/assets/{garbage-collection-test-BJmgY3IQ.js → garbage-collection-test-bPtmt69E.js} +1 -1
- package/bundled-test-harness/assets/{general-test-B5RcCakW.js → general-test-B_QwZC0y.js} +3 -3
- package/bundled-test-harness/assets/{generate-example-cards-one-shot-test-Bh9_GXLK.js → generate-example-cards-one-shot-test-DtYqN3qW.js} +1 -1
- package/bundled-test-harness/assets/{get-available-realm-identifiers-test-C18mJr3L.js → get-available-realm-identifiers-test-BiHIbpFc.js} +2 -2
- package/bundled-test-harness/assets/{get-catalog-realm-identifiers-test-vDnl-arI.js → get-catalog-realm-identifiers-test-B4EVfXvp.js} +2 -2
- package/bundled-test-harness/assets/{get-default-writable-realm-test-Co4F_EH-.js → get-default-writable-realm-test-C2izRfTp.js} +2 -2
- package/bundled-test-harness/assets/{get-published-realms-test-D6auThJu.js → get-published-realms-test-CJlYS6SA.js} +1 -1
- package/bundled-test-harness/assets/{get-realm-of-resource-identifier-test-BeVoQztL.js → get-realm-of-resource-identifier-test-DZG0gROs.js} +2 -2
- package/bundled-test-harness/assets/{get-relationship-membership-state-test-Cm_VeTXw.js → get-relationship-membership-state-test-wOVStpnA.js} +1 -1
- package/bundled-test-harness/assets/{get-user-system-card-test-CAc-Ainy.js → get-user-system-card-test-Bf_il1b_.js} +2 -2
- package/bundled-test-harness/assets/{gif-image-def-test-Co2Woq8R.js → gif-image-def-test-DD4BOFUq.js} +1 -1
- package/bundled-test-harness/assets/{gts-file-def-test-DMhWqyxZ.js → gts-file-def-test-KrlOMcTY.js} +1 -1
- package/bundled-test-harness/assets/{head-format-preview-test-DPOjt1cu.js → head-format-preview-test-CGzx-i_Q.js} +2 -2
- package/bundled-test-harness/assets/{helpers-BIQP26gX.js → helpers-CR-27yCL.js} +1 -1
- package/bundled-test-harness/assets/{host-mode-service-BYjO5JXT.js → host-mode-service-BPYfmILw.js} +1 -1
- package/bundled-test-harness/assets/{host-mode-test-D9kRy5kW.js → host-mode-test-sjKqSasU.js} +3 -3
- package/bundled-test-harness/assets/{host-submode-test-Zy7-q9vh.js → host-submode-test-CvezMbrv.js} +1 -1
- package/bundled-test-harness/assets/{hydratable-card-test-DvgHojHD.js → hydratable-card-test-Ds6x3mv5.js} +1 -1
- package/bundled-test-harness/assets/{index-query-engine-test-Bk52a889.js → index-query-engine-test-x77vbwML.js} +2 -2
- package/bundled-test-harness/assets/{index-writer-test-DNeo1Uod.js → index-writer-test-BMajX3Mj.js} +1 -1
- package/bundled-test-harness/assets/{inspector-test-OaFEP4S0.js → inspector-test-CtCAKlpG.js} +42 -5
- package/bundled-test-harness/assets/{instance-filter-matcher-test-PeeLVGMO.js → instance-filter-matcher-test-YKzjZAa3.js} +2 -2
- package/bundled-test-harness/assets/{instantiate-card-test-C0Y8FG7w.js → instantiate-card-test-Ba3rd5Zn.js} +1 -1
- package/bundled-test-harness/assets/{interact-submode-creation-and-permissions-test-Cp3YiIQG.js → interact-submode-creation-and-permissions-test-2_4tHla6.js} +4 -4
- package/bundled-test-harness/assets/{interact-submode-setup-CtFp9kvB.js → interact-submode-setup-DI2HM3S-.js} +2 -2
- package/bundled-test-harness/assets/{interact-submode-test-B_JqGk2t.js → interact-submode-test-BUKZnm-y.js} +2 -2
- package/bundled-test-harness/assets/{invalidate-realm-identifiers-test-Dpa0TzwS.js → invalidate-realm-identifiers-test-Bl1RP3Kp.js} +2 -2
- package/bundled-test-harness/assets/{invite-user-to-room-test-DXzTeCgP.js → invite-user-to-room-test-Q26QQwvj.js} +2 -2
- package/bundled-test-harness/assets/{isolated-render-test-DVzQEdsY.js → isolated-render-test-Bc2ASFB1.js} +1 -1
- package/bundled-test-harness/assets/{item-button-CAhhwhRh.js → item-button-CepLHUN-.js} +1 -1
- package/bundled-test-harness/assets/{job-priority-header-test-J8emfVrj.js → job-priority-header-test-CDDfX3mF.js} +1 -1
- package/bundled-test-harness/assets/{jpg-image-def-test-D7txmQ4U.js → jpg-image-def-test-DGjpMEj5.js} +1 -1
- package/bundled-test-harness/assets/{json-file-def-test-C3W6amHE.js → json-file-def-test-8NlQ7NyF.js} +1 -1
- package/bundled-test-harness/assets/{linksto-broken-link-placeholder-test-nZIKEYDd.js → linksto-broken-link-placeholder-test-OPR5aao3.js} +2 -2
- package/bundled-test-harness/assets/{linksto-error-sentinel-test-E5UdAPkR.js → linksto-error-sentinel-test-DNEi2-4f.js} +1 -1
- package/bundled-test-harness/assets/{linksto-many-broken-link-placeholder-test-D5lhE5y-.js → linksto-many-broken-link-placeholder-test-Bl3-UMZt.js} +2 -2
- package/bundled-test-harness/assets/{linksto-many-per-slot-access-test-uONh3sy8.js → linksto-many-per-slot-access-test-Cv88sT3k.js} +1 -1
- package/bundled-test-harness/assets/{linksto-sentinel-roundtrip-test-CUbMHhoz.js → linksto-sentinel-roundtrip-test-DDrNtJgY.js} +1 -1
- package/bundled-test-harness/assets/{linksto-singular-js-access-contract-test-Doycge43.js → linksto-singular-js-access-contract-test-CMOxHvSS.js} +1 -1
- package/bundled-test-harness/assets/{live-prerendered-search-kxxMxyHS.js → live-prerendered-search-DiFs_MHd.js} +1 -1
- package/bundled-test-harness/assets/{live-test-pbHzyWf7.js → live-test-BfSJ7dPf.js} +6 -6
- package/bundled-test-harness/assets/live-test-CfcRApCW.js +2 -0
- package/bundled-test-harness/assets/{loader-parallel-prefetch-test-cfEJV65W.js → loader-parallel-prefetch-test-DchEbilk.js} +1 -1
- package/bundled-test-harness/assets/{loader-test-DZX-dw3F.js → loader-test-LyM1F2ON.js} +1 -1
- package/bundled-test-harness/assets/{loading-test-PwEVbSuF.js → loading-test-DrK02DRI.js} +2 -2
- package/bundled-test-harness/assets/{local-storage-keys-Do9I1BSV.js → local-storage-keys-C0jyxDKn.js} +4 -1
- package/bundled-test-harness/assets/{login-ou9E1DG9.js → login-DWNfbapF.js} +1 -1
- package/bundled-test-harness/assets/{login-error-text-test-BGvtn9op.js → login-error-text-test-3lQ69Gme.js} +1 -1
- package/bundled-test-harness/assets/{m4a-audio-def-test-Dkbh40DD.js → m4a-audio-def-test-B1PZDu-M.js} +1 -1
- package/bundled-test-harness/assets/{main-CE7KR5Ht.js → main-CDat3XsY.js} +1 -1
- package/bundled-test-harness/assets/{markdown-fallback-test-BHejXXnE.js → markdown-fallback-test-D32xPo5m.js} +2 -2
- package/bundled-test-harness/assets/{markdown-file-def-test-BOvu8beB.js → markdown-file-def-test-2_0tc-pT.js} +1 -1
- package/bundled-test-harness/assets/{markdown-helpers-test-Be9UUlnA.js → markdown-helpers-test-D6Ty5K6K.js} +1 -1
- package/bundled-test-harness/assets/{markdown-highlighting-test-D-jxOaxc.js → markdown-highlighting-test-CD22pEyx.js} +2 -2
- package/bundled-test-harness/assets/{markdown-preview-CKlpPkbc.js → markdown-preview-o2AI98EN.js} +1 -1
- package/bundled-test-harness/assets/{markdown-preview-test-D2kl56R1.js → markdown-preview-test-D2YoXqUY.js} +3 -3
- package/bundled-test-harness/assets/{matrix-service-sliding-sync-test-Cl1D6ID4.js → matrix-service-sliding-sync-test-Co9EhDYF.js} +1 -1
- package/bundled-test-harness/assets/{message-service-subscription-test-OvYUTr8V.js → message-service-subscription-test-BK3W9wng.js} +2 -2
- package/bundled-test-harness/assets/{mock-matrix-CD6YHaHR.js → mock-matrix-Bkfl9ACG.js} +6 -2
- package/bundled-test-harness/assets/{mock-matrix-Dt4s2hUe.js → mock-matrix-DbxVPkSl.js} +1 -1
- package/bundled-test-harness/assets/{modal-container-wzIBYeE_.js → modal-container-BzEkpeIx.js} +1 -1
- package/bundled-test-harness/assets/{module-transpile-cache-test-Bj11UbQJ.js → module-transpile-cache-test-BFmN6_si.js} +1 -1
- package/bundled-test-harness/assets/{mp3-audio-def-test-C6tzxO6X.js → mp3-audio-def-test-DorbFtva.js} +1 -1
- package/bundled-test-harness/assets/{number-field-test-l5WRd3N9.js → number-field-test-C9F_sOf8.js} +2 -2
- package/bundled-test-harness/assets/{ogg-audio-def-test-CQ04xrfS.js → ogg-audio-def-test-DRXLSBVQ.js} +1 -1
- package/bundled-test-harness/assets/{on-key-CpWVcRaS.js → on-key-C8yMINOQ.js} +1 -1
- package/bundled-test-harness/assets/{open-create-listing-modal-test-VxITHH84.js → open-create-listing-modal-test-Yp6EOMGK.js} +1 -1
- package/bundled-test-harness/assets/open-image-in-new-tab-test-3iRCTOjd.js +52 -0
- package/bundled-test-harness/assets/{open-workspace-test-goAg_TVx.js → open-workspace-test-DrkNS6zm.js} +1 -1
- package/bundled-test-harness/assets/{operator-mode-acceptance-test-DO3lt95I.js → operator-mode-acceptance-test-DoQ5Klyi.js} +7 -7
- package/bundled-test-harness/assets/{operator-mode-card-catalog-test-C3e1--M7.js → operator-mode-card-catalog-test-Came_pKy.js} +4 -4
- package/bundled-test-harness/assets/{operator-mode-links-test-AWhMhHM2.js → operator-mode-links-test-DoTvJvpI.js} +4 -4
- package/bundled-test-harness/assets/{operator-mode-state-service-test-BICXMa5O.js → operator-mode-state-service-test-cwdudDwm.js} +2 -2
- package/bundled-test-harness/assets/{operator-mode-test-DMyFaXHK.js → operator-mode-test-DeUtV1XR.js} +4 -4
- package/bundled-test-harness/assets/{operator-mode-ui-test-z2SU5ozt.js → operator-mode-ui-test-DTUMZBlw.js} +4 -4
- package/bundled-test-harness/assets/{overlay-menu-items-test-Dkulmtpn.js → overlay-menu-items-test-DhPIUwmz.js} +3 -3
- package/bundled-test-harness/assets/{panel-BXXk_P7h.js → panel-DcMU_CGT.js} +55 -31
- package/bundled-test-harness/assets/{past-sessions-test-gKLwZO61.js → past-sessions-test-BrdqlYxe.js} +3 -3
- package/bundled-test-harness/assets/{patch-code-ClPL6B_d.js → patch-code-F_7JKtTQ.js} +1 -1
- package/bundled-test-harness/assets/{patch-code-test-CIdB45Nv.js → patch-code-test-O5_p8vp4.js} +4 -4
- package/bundled-test-harness/assets/{patch-fields-test-CBGnqUme.js → patch-fields-test-D1aSP1q_.js} +1 -1
- package/bundled-test-harness/assets/{patch-instance-test-DmDpfS3p.js → patch-instance-test-DHBeFzYI.js} +1 -1
- package/bundled-test-harness/assets/{persist-module-inspector-view-test-D6vpSfX4.js → persist-module-inspector-view-test-DDYttEKD.js} +2 -2
- package/bundled-test-harness/assets/{phone-number-field-test-DogtMkDx.js → phone-number-field-test-CUY1miSH.js} +2 -2
- package/bundled-test-harness/assets/{playground-CMnQXTzR.js → playground-DFwsIC-9.js} +2 -2
- package/bundled-test-harness/assets/{png-image-def-test-BzfrYGhY.js → png-image-def-test-C9COAyWm.js} +1 -1
- package/bundled-test-harness/assets/{prerender-file-extract-test-C-1R1B32.js → prerender-file-extract-test-B76NnPJt.js} +1 -1
- package/bundled-test-harness/assets/{prerender-html-test-1XGnbGuQ.js → prerender-html-test-ImXJjrpR.js} +1 -1
- package/bundled-test-harness/assets/{prerender-meta-test-B02oGS-5.js → prerender-meta-test-xIFFdF1X.js} +1 -1
- package/bundled-test-harness/assets/{prerender-module-test-CSKywVQA.js → prerender-module-test-CoxYOMro.js} +1 -1
- package/bundled-test-harness/assets/{prerendered-card-search-test-Cf_Hvr4P.js → prerendered-card-search-test-DLYUamOp.js} +2 -2
- package/bundled-test-harness/assets/{preview-format-Bb5FIkOY.js → preview-format-BqY_j3zZ.js} +1 -1
- package/bundled-test-harness/assets/{preview-format-test-DBKtwgvo.js → preview-format-test-CublqRWy.js} +4 -4
- package/bundled-test-harness/assets/{preview-test-dgbtaeLg.js → preview-test-CcGZEu6Y.js} +2 -2
- package/bundled-test-harness/assets/{publish-realm-test-B4c6TqTI.js → publish-realm-test-Cqq_X3L4.js} +2 -2
- package/bundled-test-harness/assets/{query-field-barrier-test-DytVxOcd.js → query-field-barrier-test-CeDBxTwq.js} +2 -2
- package/bundled-test-harness/assets/{query-field-error-sentinel-test-Cs2wXQuL.js → query-field-error-sentinel-test-CwOzGgRw.js} +2 -2
- package/bundled-test-harness/assets/{query-field-schema-test-ByfKD-mO.js → query-field-schema-test-CXt4ktVo.js} +1 -1
- package/bundled-test-harness/assets/{query-fields-test-SlJNtzM3.js → query-fields-test-CrsGkXWE.js} +1 -1
- package/bundled-test-harness/assets/{read-card-for-ai-assistant-test-BzThkf4s.js → read-card-for-ai-assistant-test-DORLxJXd.js} +2 -2
- package/bundled-test-harness/assets/{read-file-for-ai-assistant-test-CV5PoqSP.js → read-file-for-ai-assistant-test-DyyCSmMv.js} +2 -2
- package/bundled-test-harness/assets/{read-source-test-jfWyZkQO.js → read-source-test-hAUdteMO.js} +2 -2
- package/bundled-test-harness/assets/{read-text-file-test-Kg6tx07O.js → read-text-file-test-juQ-OJET.js} +2 -2
- package/bundled-test-harness/assets/{realm-oWsFVfdH.js → realm-CxU8jc8l.js} +2 -2
- package/bundled-test-harness/assets/{realm-config-routing-rule-edit-test-VyMT__jT.js → realm-config-routing-rule-edit-test-T8S_2Lwq.js} +47 -4
- package/bundled-test-harness/assets/{realm-field-test-CBmQY3Va.js → realm-field-test-wqNbmdgM.js} +2 -2
- package/bundled-test-harness/assets/{realm-indexing-test-CQ29IEno.js → realm-indexing-test-DTuwfnZZ.js} +1 -1
- package/bundled-test-harness/assets/{realm-querying-test-PR_91CCq.js → realm-querying-test-ojIOXC3n.js} +1 -1
- package/bundled-test-harness/assets/{realm-test-C6Kw7gWx.js → realm-test-MgXPmHwc.js} +1 -1
- package/bundled-test-harness/assets/{reasoning-test-M4JuH0RZ.js → reasoning-test-DcQkF04r.js} +3 -3
- package/bundled-test-harness/assets/{recent-files-cards-D845sggD.js → recent-files-cards-BICbCMhW.js} +1 -1
- package/bundled-test-harness/assets/{recent-files-test-Du5oiGDf.js → recent-files-test-Df_1aE3G.js} +2 -2
- package/bundled-test-harness/assets/{reindex-realm-test-BrgFBbOc.js → reindex-realm-test-DDYvNGWh.js} +2 -2
- package/bundled-test-harness/assets/{relationship-loading-state-test-CnCYYtmY.js → relationship-loading-state-test-C2EialRQ.js} +1 -1
- package/bundled-test-harness/assets/{render-component-BJwKMGDa.js → render-component-DLXpC-Bc.js} +1 -1
- package/bundled-test-harness/assets/{rendered-markdown-test-BvQ96-0V.js → rendered-markdown-test-DblOECt_.js} +2 -2
- package/bundled-test-harness/assets/{rich-markdown-field-test-neZFxfcc.js → rich-markdown-field-test-B34TJAq8.js} +2 -2
- package/bundled-test-harness/assets/{room-message-test-DWEcr5le.js → room-message-test-DuSkABnU.js} +3 -3
- package/bundled-test-harness/assets/{sanitize-module-list-test-B4VjLVx_.js → sanitize-module-list-test-BTFw8-Do.js} +2 -2
- package/bundled-test-harness/assets/{schema-editor-test-CHeST1JD.js → schema-editor-test-w7ANspy0.js} +1 -1
- package/bundled-test-harness/assets/{schema-generation-test-G4ZL90Sn.js → schema-generation-test-z90uBA7r.js} +3 -3
- package/bundled-test-harness/assets/{scrolling-test-D3Asc3Yr.js → scrolling-test-jCKormjp.js} +4 -4
- package/bundled-test-harness/assets/{search-and-choose-test-DMB-Nv1z.js → search-and-choose-test-BhIWdkFp.js} +2 -2
- package/bundled-test-harness/assets/{search-command-test-BNZzENdS.js → search-command-test-BlTBufTS.js} +1 -1
- package/bundled-test-harness/assets/{search-correlation-id-test-tM-SfbrA.js → search-correlation-id-test-BR7bFNCy.js} +1 -1
- package/bundled-test-harness/assets/{search-data-test-CYrjasBZ.js → search-data-test-bc2foKLa.js} +2 -2
- package/bundled-test-harness/assets/{search-google-images-test-DzFbLWZE.js → search-google-images-test-C96iDOxU.js} +1 -1
- package/bundled-test-harness/assets/{search-result-header-5VQHm_Ev.js → search-result-header-Ch7TKEzn.js} +1 -1
- package/bundled-test-harness/assets/{search-test-CBH8l5JD.js → search-test-iR0wammw.js} +2 -2
- package/bundled-test-harness/assets/{send-ai-assistant-message-test-CAlK3x0a.js → send-ai-assistant-message-test-BmJdWdzI.js} +2 -2
- package/bundled-test-harness/assets/{send-bot-trigger-event-test-CwI4Rkf8.js → send-bot-trigger-event-test-CJCAf2db.js} +2 -2
- package/bundled-test-harness/assets/{send-request-via-proxy-test-BRuk6sv0.js → send-request-via-proxy-test-DSdZppno.js} +2 -2
- package/bundled-test-harness/assets/{sending-test-BA2F7Hfk.js → sending-test-Bocu5vf9.js} +270 -12
- package/bundled-test-harness/assets/{serialization-test-DHTHfzsn.js → serialization-test-CE3TeQ4Z.js} +2 -2
- package/bundled-test-harness/assets/{set-user-system-card-test-Ct8xegEY.js → set-user-system-card-test-JZW2LcIA.js} +2 -2
- package/bundled-test-harness/assets/{setup-v4v1a2Qc.js → setup-C5QslpqI.js} +1 -1
- package/bundled-test-harness/assets/{setup-BfvQ1zfD.js → setup-CN-HHlT_.js} +2 -2
- package/bundled-test-harness/assets/{show-card-test-7VGIdTJh.js → show-card-test-B41I3EWZ.js} +3 -3
- package/bundled-test-harness/assets/{skills-test-NKDA1G9S.js → skills-test-Cut0gpNU.js} +3 -3
- package/bundled-test-harness/assets/{spec-test-61E0gdIB.js → spec-test-DytzFxZb.js} +3 -3
- package/bundled-test-harness/assets/{store-BM5pUF94.js → store-CbIxTljQ.js} +30 -0
- package/bundled-test-harness/assets/{store-add-test-mRtjroP0.js → store-add-test-ulvv9A3X.js} +2 -2
- package/bundled-test-harness/assets/{store-test-CVHw6LMN.js → store-test-C747NJ3O.js} +77 -4
- package/bundled-test-harness/assets/{submode-switcher-Popj4iN5.js → submode-switcher-iR4m0GzD.js} +1 -1
- package/bundled-test-harness/assets/{summarize-session-test-UZOGVM_F.js → summarize-session-test-BcXrj1r3.js} +2 -2
- package/bundled-test-harness/assets/{svg-image-def-test-Dqjy84jw.js → svg-image-def-test-DW1rtFSA.js} +1 -1
- package/bundled-test-harness/assets/{switch-submode-DOdRs5QD.js → switch-submode--ZVbWG3S.js} +1 -1
- package/bundled-test-harness/assets/{switch-submode-test-MWnyo759.js → switch-submode-test--Ncx8g_l.js} +3 -3
- package/bundled-test-harness/assets/{test-support-BfonQA4V.js → test-support-CCargU9V.js} +1 -1
- package/bundled-test-harness/assets/{tests-DQLSvmHe.js → tests-Dw_agY8k.js} +265 -263
- package/bundled-test-harness/assets/{text-file-def-test-DlyCDiM4.js → text-file-def-test-Bl2R6NO8.js} +1 -1
- package/bundled-test-harness/assets/{text-input-validator-test-Ccx-4gLo.js → text-input-validator-test-CAlDivoV.js} +3 -3
- package/bundled-test-harness/assets/{text-suggestion-test-mIvJOTS7.js → text-suggestion-test-CbJWk97Q.js} +1 -1
- package/bundled-test-harness/assets/{theme-card-test-Bs3Q034n.js → theme-card-test-Q5eP-lEF.js} +3 -3
- package/bundled-test-harness/assets/{transform-cards-test-BsTtRP0g.js → transform-cards-test-3PsuM2Sv.js} +2 -2
- package/bundled-test-harness/assets/{ts-file-def-test-DtWzgXkt.js → ts-file-def-test-BoXA3RgL.js} +1 -1
- package/bundled-test-harness/assets/{unpublish-realm-test-BFJEMQL7.js → unpublish-realm-test-CgiIcZ6j.js} +2 -2
- package/bundled-test-harness/assets/{update-room-skills-test-BrFhA3El.js → update-room-skills-test-B-BI7daL.js} +3 -3
- package/bundled-test-harness/assets/{use-ai-assistant-test-BsyBY6-a.js → use-ai-assistant-test-BEiEjFOH.js} +2 -2
- package/bundled-test-harness/assets/user-message-Bbw4pQmd.css +22 -0
- package/bundled-test-harness/assets/{user-message-BFN7dtqK.js → user-message-CVG3cgJq.js} +2 -2
- package/bundled-test-harness/assets/{validate-realm-test-DQlQ-pWZ.js → validate-realm-test-DBx-3YG9.js} +2 -2
- package/bundled-test-harness/assets/{wav-audio-def-test-BZ0oLTT1.js → wav-audio-def-test-CPJl6Hpr.js} +1 -1
- package/bundled-test-harness/assets/{webp-image-def-test-tuOTQeTt.js → webp-image-def-test-Bh3SOpDa.js} +1 -1
- package/bundled-test-harness/assets/{workspace-DvhB0Ltb.js → workspace-PBphyb9N.js} +2 -2
- package/bundled-test-harness/assets/{workspace-chooser-delete-test-D_Gp78-R.js → workspace-chooser-delete-test-1n1lqK_X.js} +3 -3
- package/bundled-test-harness/assets/{workspace-chooser-test-CuJ4pgJh.js → workspace-chooser-test-wcKYsTgx.js} +1 -1
- package/bundled-test-harness/assets/{workspace-delete-multiple-test-BUmKPHGp.js → workspace-delete-multiple-test-DlXWFVK1.js} +1 -1
- package/bundled-test-harness/assets/{workspace-delete-summary-test-B8qyNd7w.js → workspace-delete-summary-test-iqD1ae55.js} +1 -1
- package/bundled-test-harness/assets/{write-binary-file-test-D1h4TED_.js → write-binary-file-test-BkADCn85.js} +2 -2
- package/bundled-test-harness/assets/{write-text-file-test-DKA9TpIm.js → write-text-file-test-C9K0doTU.js} +2 -2
- package/bundled-test-harness/boxel-ui-checksum.txt +1 -1
- package/bundled-test-harness/index.html +33 -33
- package/bundled-test-harness/tests/index.html +36 -36
- package/bundled-types/base/field-component.d.ts +15 -4
- package/bundled-types/base/links-to-editor.d.ts +9 -0
- package/bundled-types/boxel-ui/components/filter-list/index.gts +4 -1
- package/bundled-types/host-app/components/ai-assistant/chat-input/index.gts +2 -1
- package/bundled-types/host-app/components/ai-assistant/message/user-message.gts +6 -2
- package/bundled-types/host-app/components/matrix/room.gts +115 -44
- package/bundled-types/host-app/lib/matrix-classes/message-builder.ts +13 -0
- package/bundled-types/host-app/services/local-persistence-service.ts +179 -0
- package/bundled-types/host-app/services/matrix-service.ts +372 -1
- package/bundled-types/host-app/services/store.ts +70 -0
- package/bundled-types/host-app/utils/local-storage-keys.ts +2 -0
- package/bundled-types/host-tests/helpers/mock-matrix/_client.ts +3 -0
- package/bundled-types/host-tests/helpers/mock-matrix/_utils.ts +3 -0
- package/bundled-types/host-tests/helpers/mock-matrix.ts +1 -0
- package/dist/index.js +257 -253
- package/package.json +3 -3
- package/src/commands/realm/index.ts +2 -0
- package/src/commands/realm/ingest-card.ts +567 -0
- package/src/commands/realm/publish.ts +87 -16
- package/src/commands/realm/pull.ts +9 -13
- package/src/commands/realm/push.ts +10 -14
- package/src/commands/realm/status.ts +14 -18
- package/src/commands/realm/sync.ts +9 -13
- package/src/commands/realm/unpublish.ts +11 -0
- package/src/lib/auth-resolver.ts +15 -2
- package/bundled-test-harness/assets/adapter-Dk9jvNQb.js +0 -2
- package/bundled-test-harness/assets/live-test-B7uB4aVp.js +0 -2
- package/bundled-test-harness/assets/user-message-B8olA3Ml.css +0 -18
- /package/bundled-test-harness/assets/{ai-assistant-panel-service-test-B2pqk_1r.js → ai-assistant-panel-service-test-DEeul-zv.js} +0 -0
- /package/bundled-test-harness/assets/{amd-transpile-test-ftXbwnFz.js → amd-transpile-test-DmEkMdCo.js} +0 -0
- /package/bundled-test-harness/assets/{apply-boxel-formatting-test-BSzr4sNI.js → apply-boxel-formatting-test-RixVcq5N.js} +0 -0
- /package/bundled-test-harness/assets/{auth-error-guard-test-BxIq12aN.js → auth-error-guard-test-beazl6s5.js} +0 -0
- /package/bundled-test-harness/assets/{bfm-card-references-test-6aAhfBzH.js → bfm-card-references-test-IEbg0jo-.js} +0 -0
- /package/bundled-test-harness/assets/{cached-fetch-test-CPr-eiq_.js → cached-fetch-test-DlnnpQGz.js} +0 -0
- /package/bundled-test-harness/assets/{card-directory-name-test-BS8WD3oH.js → card-directory-name-test-QKl1Ykz6.js} +0 -0
- /package/bundled-test-harness/assets/{card-search-query-builder-test-zp6muUB1.js → card-search-query-builder-test-BWc5lDv3.js} +0 -0
- /package/bundled-test-harness/assets/{code-patching-test-BZPvPsMr.js → code-patching-test-BRNMumI6.js} +0 -0
- /package/bundled-test-harness/assets/{code-semantics-service-test-BBjJ3EF3.js → code-semantics-service-test-CJOSUAQH.js} +0 -0
- /package/bundled-test-harness/assets/{command-definitions-test-BcMJzIBM.js → command-definitions-test-De0BMqHI.js} +0 -0
- /package/bundled-test-harness/assets/{extract-css-variables-test-FIZxFxaL.js → extract-css-variables-test-Di5CFXG-.js} +0 -0
- /package/bundled-test-harness/assets/{fetcher-test-g2cjjXxV.js → fetcher-test-Cb8cS9JN.js} +0 -0
- /package/bundled-test-harness/assets/{field-path-parser-test-DkY-DFQN.js → field-path-parser-test-Db4kG7EB.js} +0 -0
- /package/bundled-test-harness/assets/{file-def-manager-canonicalize-test-Dlf4HlLX.js → file-def-manager-canonicalize-test-Cq5B5KN4.js} +0 -0
- /package/bundled-test-harness/assets/{generate-css-variables-test-De4LPdBt.js → generate-css-variables-test-BahavIHR.js} +0 -0
- /package/bundled-test-harness/assets/{get-type-refs-from-filter-test-DmDF_dTY.js → get-type-refs-from-filter-test-CH5flf8B.js} +0 -0
- /package/bundled-test-harness/assets/{last-modified-date-test-C2hEJ3xU.js → last-modified-date-test-C_jV0b05.js} +0 -0
- /package/bundled-test-harness/assets/{limited-set-test-SLbA1cwS.js → limited-set-test-CcpIJCrn.js} +0 -0
- /package/bundled-test-harness/assets/{loader-icon-error-test-DTo5t1OQ.js → loader-icon-error-test-Bc_L-0Zb.js} +0 -0
- /package/bundled-test-harness/assets/{loader-retry-test-CPFmHSUN.js → loader-retry-test-DQ0E0a0N.js} +0 -0
- /package/bundled-test-harness/assets/{marked-sync-test-CaZYJo4x.js → marked-sync-test-JSqOc6hu.js} +0 -0
- /package/bundled-test-harness/assets/{mutex-test-p2qp1xRj.js → mutex-test-BDkeJutn.js} +0 -0
- /package/bundled-test-harness/assets/{plan-install-test-CrYUs1-G.js → plan-install-test-fUZIttPZ.js} +0 -0
- /package/bundled-test-harness/assets/{qs-test-DEH8SHFS.js → qs-test-CminVD53.js} +0 -0
- /package/bundled-test-harness/assets/{query-field-normalization-test-DrqBkUxD.js → query-field-normalization-test-B9alzE_u.js} +0 -0
- /package/bundled-test-harness/assets/{queue-test-CS3aOeHM.js → queue-test-BvWT6K7Z.js} +0 -0
- /package/bundled-test-harness/assets/{realm-index-card-id-test-FV_gOG_K.js → realm-index-card-id-test-hvCyEpGZ.js} +0 -0
- /package/bundled-test-harness/assets/{realm-paths-test-CvXB4BUZ.js → realm-paths-test-DrwpPXyh.js} +0 -0
- /package/bundled-test-harness/assets/{render-component-BabSF5nE.js → render-component-DY19erxA.js} +0 -0
- /package/bundled-test-harness/assets/{render-error-test-CvMDARjN.js → render-error-test-BC4QmstW.js} +0 -0
- /package/bundled-test-harness/assets/{render-service-test-DRCvv7lo.js → render-service-test-BkCkB3a2.js} +0 -0
- /package/bundled-test-harness/assets/{render-timer-stub-test-CVa_rjXp.js → render-timer-stub-test-cnMPidgA.js} +0 -0
- /package/bundled-test-harness/assets/{search-cache-key-test-r83Xl6Io.js → search-cache-key-test-DI0DKzU5.js} +0 -0
- /package/bundled-test-harness/assets/{search-in-flight-key-test-BmqFzX6o.js → search-in-flight-key-test-DyRDbEX1.js} +0 -0
- /package/bundled-test-harness/assets/{unified-search-results-test-D9v-CCog.js → unified-search-results-test-BF8Dps_j.js} +0 -0
- /package/bundled-test-harness/assets/{url-test-DtekKUme.js → url-test-DkEL_mbR.js} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardstack/boxel-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-unstable.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "CLI tools for Boxel workspace management",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
"ts-node": "^10.9.1",
|
|
63
63
|
"vite": "^6.3.2",
|
|
64
64
|
"vitest": "^2.1.9",
|
|
65
|
-
"@cardstack/local-types": "0.0.0",
|
|
66
65
|
"@cardstack/postgres": "0.0.0",
|
|
67
|
-
"@cardstack/runtime-common": "1.0.0"
|
|
66
|
+
"@cardstack/runtime-common": "1.0.0",
|
|
67
|
+
"@cardstack/local-types": "0.0.0"
|
|
68
68
|
},
|
|
69
69
|
"publishConfig": {
|
|
70
70
|
"access": "public",
|
|
@@ -3,6 +3,7 @@ import { registerCancelIndexingCommand } from './cancel-indexing.ts';
|
|
|
3
3
|
import { registerCreateCommand } from './create.ts';
|
|
4
4
|
import { registerHistoryCommand } from './history.ts';
|
|
5
5
|
import { registerIndexingErrorsCommand } from './indexing-errors.ts';
|
|
6
|
+
import { registerIngestCardCommand } from './ingest-card.ts';
|
|
6
7
|
import { registerListCommand } from './list.ts';
|
|
7
8
|
import { registerMilestoneCommand } from './milestone.ts';
|
|
8
9
|
import { registerPublishCommand } from './publish.ts';
|
|
@@ -24,6 +25,7 @@ export function registerRealmCommand(program: Command): void {
|
|
|
24
25
|
registerCreateCommand(realm);
|
|
25
26
|
registerHistoryCommand(realm);
|
|
26
27
|
registerIndexingErrorsCommand(realm);
|
|
28
|
+
registerIngestCardCommand(realm);
|
|
27
29
|
registerListCommand(realm);
|
|
28
30
|
registerMilestoneCommand(realm);
|
|
29
31
|
registerPublishCommand(realm);
|
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { ensureTrailingSlash } from '@cardstack/runtime-common/paths';
|
|
4
|
+
import {
|
|
5
|
+
RealmSyncBase,
|
|
6
|
+
SupportedMimeType,
|
|
7
|
+
type SyncOptions,
|
|
8
|
+
} from '../../lib/realm-sync-base.ts';
|
|
9
|
+
import {
|
|
10
|
+
CheckpointManager,
|
|
11
|
+
type CheckpointChange,
|
|
12
|
+
} from '../../lib/checkpoint-manager.ts';
|
|
13
|
+
import { resolveRealmAuthenticator } from '../../lib/auth-resolver.ts';
|
|
14
|
+
import { resolveRealmSecretSeed } from '../../lib/prompt.ts';
|
|
15
|
+
import {
|
|
16
|
+
getProfileManager,
|
|
17
|
+
type ProfileManager,
|
|
18
|
+
} from '../../lib/profile-manager.ts';
|
|
19
|
+
import type { RealmAuthenticator } from '../../lib/realm-authenticator.ts';
|
|
20
|
+
import { search } from '../search.ts';
|
|
21
|
+
|
|
22
|
+
const CARD_JSON = 'application/vnd.card+json';
|
|
23
|
+
const MODULE_EXTENSIONS = ['.gts', '.gjs', '.ts', '.js'];
|
|
24
|
+
const SPEC_MODULE = 'https://cardstack.com/base/spec';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The realm index identifies modules without their executable extension;
|
|
28
|
+
* strip it whenever a module path is used in a type filter or compared
|
|
29
|
+
* against an indexed module reference.
|
|
30
|
+
*/
|
|
31
|
+
function stripModuleExt(moduleRelOrUrl: string): string {
|
|
32
|
+
return moduleRelOrUrl.replace(/\.(gts|gjs|ts|js)$/, '');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Pull every module-specifier out of `.gts`/`.ts` source text. Matches the
|
|
37
|
+
* `from '<spec>'` clause of every `import`/`export … from` (value **and**
|
|
38
|
+
* `import type`, namespace, re-export) plus side-effect `import '<spec>'`.
|
|
39
|
+
* Type-only imports matter: they are erased at transpile, so the realm's
|
|
40
|
+
* runtime dep graph misses them — yet the seeded copy still needs the file
|
|
41
|
+
* on disk for `boxel parse` to type-check.
|
|
42
|
+
*/
|
|
43
|
+
export function extractImportSpecifiers(source: string): string[] {
|
|
44
|
+
let specs = new Set<string>();
|
|
45
|
+
let fromRe = /\bfrom\s*['"]([^'"]+)['"]/g;
|
|
46
|
+
let sideEffectRe = /\bimport\s*['"]([^'"]+)['"]/g;
|
|
47
|
+
let m: RegExpExecArray | null;
|
|
48
|
+
while ((m = fromRe.exec(source))) specs.add(m[1]);
|
|
49
|
+
while ((m = sideEffectRe.exec(source))) specs.add(m[1]);
|
|
50
|
+
return [...specs];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Exported card/field class names declared in a module (for instance lookup). */
|
|
54
|
+
export function extractExportedClassNames(source: string): string[] {
|
|
55
|
+
let names = new Set<string>();
|
|
56
|
+
let re =
|
|
57
|
+
/\bexport\s+(?:default\s+)?(?:abstract\s+)?class\s+(\w+)\s+extends\b/g;
|
|
58
|
+
let m: RegExpExecArray | null;
|
|
59
|
+
while ((m = re.exec(source))) names.add(m[1]);
|
|
60
|
+
return [...names];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a same-realm import specifier to a realm-relative file path that
|
|
65
|
+
* exists in `fileSet`. Handles relative (`./`, `../`), same-origin absolute
|
|
66
|
+
* (`https://…/<realm>/…`), and registered-prefix (`@cardstack/<realm>/…`)
|
|
67
|
+
* forms. Returns null for anything outside this realm (base realm, other
|
|
68
|
+
* realms, bare npm packages) — those resolve at runtime and aren't copied.
|
|
69
|
+
*/
|
|
70
|
+
export function resolveSameRealmFile(
|
|
71
|
+
spec: string,
|
|
72
|
+
fromAbsUrl: string,
|
|
73
|
+
realmRoot: string,
|
|
74
|
+
fileSet: Set<string>,
|
|
75
|
+
): string | null {
|
|
76
|
+
let rel: string;
|
|
77
|
+
if (spec.startsWith('.') || spec.startsWith('/')) {
|
|
78
|
+
let absUrl = new URL(spec, fromAbsUrl).href;
|
|
79
|
+
if (!absUrl.startsWith(realmRoot)) return null; // base realm / other realm
|
|
80
|
+
rel = absUrl.slice(realmRoot.length).replace(/^\/+/, '');
|
|
81
|
+
} else if (/^https?:\/\//.test(spec)) {
|
|
82
|
+
if (!spec.startsWith(realmRoot)) return null;
|
|
83
|
+
rel = spec.slice(realmRoot.length).replace(/^\/+/, '');
|
|
84
|
+
} else if (spec.startsWith('@')) {
|
|
85
|
+
// Registered-prefix form (`@cardstack/<realm>/…`). Map onto this realm by
|
|
86
|
+
// its path tail (e.g. `catalog/`). npm-scoped packages (`@glimmer/…`)
|
|
87
|
+
// won't contain the realm tail and fall through to null (external).
|
|
88
|
+
let tail = new URL(realmRoot).pathname.replace(/^\/+/, '');
|
|
89
|
+
let idx = tail ? spec.indexOf(tail) : -1;
|
|
90
|
+
if (idx < 0) return null;
|
|
91
|
+
rel = spec.slice(idx + tail.length).replace(/^\/+/, '');
|
|
92
|
+
} else {
|
|
93
|
+
return null; // bare npm module — external
|
|
94
|
+
}
|
|
95
|
+
let candidates = MODULE_EXTENSIONS.some((ext) => rel.endsWith(ext))
|
|
96
|
+
? [rel]
|
|
97
|
+
: [rel, ...MODULE_EXTENSIONS.map((ext) => rel + ext)];
|
|
98
|
+
for (let cand of candidates) {
|
|
99
|
+
if (fileSet.has(cand)) return cand;
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class RealmCardIngester extends RealmSyncBase {
|
|
105
|
+
hasError = false;
|
|
106
|
+
copiedFiles: string[] = [];
|
|
107
|
+
private profileManager: ProfileManager;
|
|
108
|
+
private cardUrl: string;
|
|
109
|
+
private sourceCache = new Map<string, string | null>();
|
|
110
|
+
|
|
111
|
+
constructor(
|
|
112
|
+
options: SyncOptions & { cardUrl: string },
|
|
113
|
+
authenticator: RealmAuthenticator,
|
|
114
|
+
profileManager: ProfileManager,
|
|
115
|
+
) {
|
|
116
|
+
super(options, authenticator);
|
|
117
|
+
this.profileManager = profileManager;
|
|
118
|
+
this.cardUrl = options.cardUrl;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private get realmRoot(): string {
|
|
122
|
+
return this.normalizedRealmUrl; // always ends with '/'
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private relToAbs(rel: string): string {
|
|
126
|
+
return this.realmRoot + rel.replace(/^\/+/, '');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private toRel(absUrl: string): string {
|
|
130
|
+
return absUrl.startsWith(this.realmRoot)
|
|
131
|
+
? absUrl.slice(this.realmRoot.length).replace(/^\/+/, '')
|
|
132
|
+
: absUrl;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Normalize any reference to a realm-relative path. The realm is reachable
|
|
137
|
+
* under two URL spaces: the served root (`https://…/catalog/`, used by file
|
|
138
|
+
* I/O and `_mtimes`) and a published alias (`@cardstack/catalog/`, used by
|
|
139
|
+
* search-result `id`s and `ref.module`). Both share the realm's path tail
|
|
140
|
+
* (`catalog/`), so we relativize against that.
|
|
141
|
+
*/
|
|
142
|
+
private relativize(url: string): string {
|
|
143
|
+
if (url.startsWith(this.realmRoot)) {
|
|
144
|
+
return url.slice(this.realmRoot.length).replace(/^\/+/, '');
|
|
145
|
+
}
|
|
146
|
+
let tail = new URL(this.realmRoot).pathname.replace(/^\/+/, ''); // e.g. catalog/
|
|
147
|
+
let idx = tail ? url.indexOf(tail) : -1;
|
|
148
|
+
if (idx >= 0) return url.slice(idx + tail.length).replace(/^\/+/, '');
|
|
149
|
+
return url.replace(/^\/+/, '');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Resolve a module ref (absolute alias/https or relative) to a realm-relative path. */
|
|
153
|
+
private refToRel(refModule: string, baseRel: string): string {
|
|
154
|
+
if (/^https?:\/\//.test(refModule) || refModule.startsWith('@')) {
|
|
155
|
+
return this.relativize(refModule);
|
|
156
|
+
}
|
|
157
|
+
return new URL(refModule, `https://_/${baseRel}`).pathname.replace(
|
|
158
|
+
/^\/+/,
|
|
159
|
+
'',
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Fetch a realm file's source text (cached). Null on non-OK. */
|
|
164
|
+
private async fetchText(rel: string): Promise<string | null> {
|
|
165
|
+
if (this.sourceCache.has(rel)) return this.sourceCache.get(rel)!;
|
|
166
|
+
let res = await this.authenticator.authedRealmFetch(
|
|
167
|
+
this.buildFileUrl(rel),
|
|
168
|
+
{
|
|
169
|
+
headers: { Accept: SupportedMimeType.CardSource },
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
let text = res.ok ? await res.text() : null;
|
|
173
|
+
this.sourceCache.set(rel, text);
|
|
174
|
+
return text;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async sync(): Promise<void> {
|
|
178
|
+
let cardUrl = this.cardUrl;
|
|
179
|
+
let fileSet = new Set((await this.getRemoteMtimes()).keys());
|
|
180
|
+
if (fileSet.size === 0) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Source realm ${this.realmRoot} returned no files (check the URL and your access).`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let toCopy = new Set<string>();
|
|
187
|
+
let entry = await this.resolveEntry(cardUrl, fileSet);
|
|
188
|
+
|
|
189
|
+
// 1. Module dependency graph (static imports, transitive, same-realm).
|
|
190
|
+
let moduleFiles = await this.crawlModules(entry.moduleRels, fileSet);
|
|
191
|
+
for (let f of moduleFiles) toCopy.add(f);
|
|
192
|
+
|
|
193
|
+
// 2. Co-located tests for every seeded module.
|
|
194
|
+
for (let f of moduleFiles) {
|
|
195
|
+
let test = f.replace(/\.(gts|gjs|ts|js)$/, '.test.$1');
|
|
196
|
+
if (test !== f && fileSet.has(test)) toCopy.add(test);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// 3. The entry card's own instances.
|
|
200
|
+
let entryModuleAbs = entry.moduleRels.map((r) => this.relToAbs(r));
|
|
201
|
+
let instanceRels = await this.findEntryInstances(
|
|
202
|
+
moduleFiles,
|
|
203
|
+
entryModuleAbs,
|
|
204
|
+
fileSet,
|
|
205
|
+
);
|
|
206
|
+
for (let r of entry.instanceRels) instanceRels.add(r);
|
|
207
|
+
for (let r of instanceRels) toCopy.add(r);
|
|
208
|
+
|
|
209
|
+
// 4. The card's own Catalog Spec(s) — card/app specType only.
|
|
210
|
+
let specRels = await this.findCardSpecs(moduleFiles, fileSet);
|
|
211
|
+
for (let r of specRels) toCopy.add(r);
|
|
212
|
+
|
|
213
|
+
if (toCopy.size === 0) {
|
|
214
|
+
throw new Error(`Nothing to ingest for ${cardUrl}.`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
await this.downloadAll([...toCopy], fileSet);
|
|
218
|
+
await this.writeCheckpoint();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Classify the entry URL as a module or an instance and seed the crawl. */
|
|
222
|
+
private async resolveEntry(
|
|
223
|
+
cardUrl: string,
|
|
224
|
+
fileSet: Set<string>,
|
|
225
|
+
): Promise<{ moduleRels: string[]; instanceRels: string[] }> {
|
|
226
|
+
let rel = this.toRel(cardUrl.replace(/\/$/, ''));
|
|
227
|
+
// Instance? Canonical instance URLs omit the `.json` (e.g. `.../Person/1`),
|
|
228
|
+
// so probe the `.json` file rather than the bare path (which 404s).
|
|
229
|
+
let instanceRel = rel.endsWith('.json') ? rel : `${rel}.json`;
|
|
230
|
+
if (fileSet.has(instanceRel)) {
|
|
231
|
+
let source = await this.fetchText(instanceRel);
|
|
232
|
+
let adoptsFrom =
|
|
233
|
+
source != null
|
|
234
|
+
? tryParseCardDoc(source)?.data?.meta?.adoptsFrom?.module
|
|
235
|
+
: undefined;
|
|
236
|
+
if (adoptsFrom) {
|
|
237
|
+
// Instance: seed from its definition module, copy the instance.
|
|
238
|
+
let moduleFile = resolveSameRealmFile(
|
|
239
|
+
adoptsFrom,
|
|
240
|
+
this.relToAbs(instanceRel),
|
|
241
|
+
this.realmRoot,
|
|
242
|
+
fileSet,
|
|
243
|
+
);
|
|
244
|
+
return {
|
|
245
|
+
moduleRels: moduleFile ? [moduleFile] : [],
|
|
246
|
+
instanceRels: [instanceRel],
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Module: resolve to a real source file.
|
|
251
|
+
let moduleFile = resolveSameRealmFile(
|
|
252
|
+
cardUrl,
|
|
253
|
+
this.realmRoot,
|
|
254
|
+
this.realmRoot,
|
|
255
|
+
fileSet,
|
|
256
|
+
);
|
|
257
|
+
if (!moduleFile) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`Could not resolve ${cardUrl} to a module or instance in ${this.realmRoot}.`,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
return { moduleRels: [moduleFile], instanceRels: [] };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** BFS the same-realm import graph from the seed modules. */
|
|
266
|
+
private async crawlModules(
|
|
267
|
+
seeds: string[],
|
|
268
|
+
fileSet: Set<string>,
|
|
269
|
+
): Promise<Set<string>> {
|
|
270
|
+
let seen = new Set<string>();
|
|
271
|
+
let queue = [...seeds];
|
|
272
|
+
while (queue.length) {
|
|
273
|
+
let rel = queue.shift()!;
|
|
274
|
+
if (seen.has(rel)) continue;
|
|
275
|
+
seen.add(rel);
|
|
276
|
+
let source = await this.fetchText(rel);
|
|
277
|
+
if (source == null) continue;
|
|
278
|
+
for (let spec of extractImportSpecifiers(source)) {
|
|
279
|
+
let dep = resolveSameRealmFile(
|
|
280
|
+
spec,
|
|
281
|
+
this.relToAbs(rel),
|
|
282
|
+
this.realmRoot,
|
|
283
|
+
fileSet,
|
|
284
|
+
);
|
|
285
|
+
if (dep && !seen.has(dep)) queue.push(dep);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return seen;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/** Instances whose definition is one of the entry module's exported cards. */
|
|
292
|
+
private async findEntryInstances(
|
|
293
|
+
moduleFiles: Set<string>,
|
|
294
|
+
entryModuleAbs: string[],
|
|
295
|
+
fileSet: Set<string>,
|
|
296
|
+
): Promise<Set<string>> {
|
|
297
|
+
let out = new Set<string>();
|
|
298
|
+
for (let rel of moduleFiles) {
|
|
299
|
+
let moduleAbs = this.relToAbs(rel);
|
|
300
|
+
if (!entryModuleAbs.includes(moduleAbs)) continue;
|
|
301
|
+
let source = await this.fetchText(rel);
|
|
302
|
+
if (source == null) continue;
|
|
303
|
+
for (let name of extractExportedClassNames(source)) {
|
|
304
|
+
let results = await this.searchCards({
|
|
305
|
+
filter: { type: { module: stripModuleExt(moduleAbs), name } },
|
|
306
|
+
});
|
|
307
|
+
for (let card of results) {
|
|
308
|
+
let r = this.cardIdToInstanceRel(card.id);
|
|
309
|
+
if (r && fileSet.has(r)) out.add(r);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return out;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** Card/app Spec cards whose `ref` resolves to a seeded module. */
|
|
317
|
+
private async findCardSpecs(
|
|
318
|
+
moduleFiles: Set<string>,
|
|
319
|
+
fileSet: Set<string>,
|
|
320
|
+
): Promise<Set<string>> {
|
|
321
|
+
let out = new Set<string>();
|
|
322
|
+
let moduleRelsNoExt = new Set([...moduleFiles].map(stripModuleExt));
|
|
323
|
+
let specs = await this.searchCards({
|
|
324
|
+
filter: { type: { module: SPEC_MODULE, name: 'Spec' } },
|
|
325
|
+
});
|
|
326
|
+
for (let spec of specs) {
|
|
327
|
+
let attrs = spec.attributes ?? {};
|
|
328
|
+
let specType = attrs.specType;
|
|
329
|
+
if (specType !== 'card' && specType !== 'app') continue;
|
|
330
|
+
let ref = attrs.ref as { module?: string } | undefined;
|
|
331
|
+
if (!ref?.module || !spec.id) continue;
|
|
332
|
+
let refRel = stripModuleExt(
|
|
333
|
+
this.refToRel(ref.module, this.relativize(spec.id)),
|
|
334
|
+
);
|
|
335
|
+
if (!moduleRelsNoExt.has(refRel)) continue;
|
|
336
|
+
let r = this.cardIdToInstanceRel(spec.id);
|
|
337
|
+
if (r && fileSet.has(r)) out.add(r);
|
|
338
|
+
}
|
|
339
|
+
return out;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private async searchCards(
|
|
343
|
+
query: Record<string, unknown>,
|
|
344
|
+
): Promise<CardResource[]> {
|
|
345
|
+
let result = await search([this.realmRoot], query, {
|
|
346
|
+
profileManager: this.profileManager,
|
|
347
|
+
});
|
|
348
|
+
if (!result.ok) {
|
|
349
|
+
this.hasError = true;
|
|
350
|
+
console.warn(` search failed: ${result.error ?? 'unknown'}`);
|
|
351
|
+
return [];
|
|
352
|
+
}
|
|
353
|
+
return (result.data ?? []) as CardResource[];
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private cardIdToInstanceRel(id: string | undefined): string | null {
|
|
357
|
+
if (!id) return null;
|
|
358
|
+
let rel = this.relativize(id);
|
|
359
|
+
if (!rel) return null;
|
|
360
|
+
return rel.endsWith('.json') ? rel : `${rel}.json`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private async downloadAll(
|
|
364
|
+
rels: string[],
|
|
365
|
+
_fileSet: Set<string>,
|
|
366
|
+
): Promise<void> {
|
|
367
|
+
let results = await Promise.all(
|
|
368
|
+
rels.map((rel) =>
|
|
369
|
+
this.remoteLimit(async () => {
|
|
370
|
+
try {
|
|
371
|
+
await this.downloadFile(rel, path.join(this.options.localDir, rel));
|
|
372
|
+
return rel;
|
|
373
|
+
} catch (error) {
|
|
374
|
+
this.hasError = true;
|
|
375
|
+
console.error(`Error downloading ${rel}:`, error);
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
}),
|
|
379
|
+
),
|
|
380
|
+
);
|
|
381
|
+
this.copiedFiles = results.filter((r): r is string => r !== null);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Best-effort: a checkpoint failure (e.g. unwritable history dir) is
|
|
386
|
+
* warned about but doesn't fail the ingest — the files are already copied.
|
|
387
|
+
*/
|
|
388
|
+
private async writeCheckpoint(): Promise<void> {
|
|
389
|
+
if (this.options.dryRun || this.copiedFiles.length === 0) return;
|
|
390
|
+
let changes: CheckpointChange[] = this.copiedFiles.map((file) => ({
|
|
391
|
+
file,
|
|
392
|
+
status: 'modified' as const,
|
|
393
|
+
}));
|
|
394
|
+
try {
|
|
395
|
+
let checkpoint = await new CheckpointManager(
|
|
396
|
+
this.options.localDir,
|
|
397
|
+
).createCheckpoint(
|
|
398
|
+
'remote',
|
|
399
|
+
changes,
|
|
400
|
+
`Ingest card: ${this.copiedFiles.length} files`,
|
|
401
|
+
);
|
|
402
|
+
if (checkpoint) {
|
|
403
|
+
let tag = checkpoint.isMajor ? '[MAJOR]' : '[minor]';
|
|
404
|
+
console.log(
|
|
405
|
+
`\nCheckpoint created: ${checkpoint.shortHash} ${tag} ${checkpoint.message}`,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
} catch (error) {
|
|
409
|
+
console.warn(
|
|
410
|
+
`Warning: failed to create checkpoint: ${error instanceof Error ? error.message : String(error)}`,
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
interface CardResource {
|
|
417
|
+
id?: string;
|
|
418
|
+
attributes?: { specType?: string; ref?: unknown; [k: string]: unknown };
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function tryParseCardDoc(
|
|
422
|
+
source: string,
|
|
423
|
+
): { data?: { meta?: { adoptsFrom?: { module?: string } } } } | null {
|
|
424
|
+
try {
|
|
425
|
+
let parsed = JSON.parse(source);
|
|
426
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
427
|
+
} catch {
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export interface IngestCardCommandOptions {
|
|
433
|
+
realm?: string;
|
|
434
|
+
dryRun?: boolean;
|
|
435
|
+
realmSecretSeed?: string;
|
|
436
|
+
profileManager?: ProfileManager;
|
|
437
|
+
/**
|
|
438
|
+
* @internal Test hook: supply an already-constructed authenticator,
|
|
439
|
+
* bypassing both seed resolution and the profile flow.
|
|
440
|
+
*/
|
|
441
|
+
authenticator?: RealmAuthenticator;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export async function ingestCard(
|
|
445
|
+
cardUrl: string,
|
|
446
|
+
localDir: string,
|
|
447
|
+
options: IngestCardCommandOptions,
|
|
448
|
+
): Promise<{ files: string[]; error?: string }> {
|
|
449
|
+
// A card URL never ends in a slash; strip one a copy-paste may have added.
|
|
450
|
+
// It would otherwise skew seed-auth registration (a token scoped to the
|
|
451
|
+
// card path rather than the realm) and realm auto-detection below.
|
|
452
|
+
cardUrl = cardUrl.replace(/\/$/, '');
|
|
453
|
+
let pm = options.profileManager ?? getProfileManager();
|
|
454
|
+
let resolution = resolveRealmAuthenticator({
|
|
455
|
+
realmUrl: options.realm ?? cardUrl,
|
|
456
|
+
realmSecretSeed: options.realmSecretSeed,
|
|
457
|
+
profileManager: pm,
|
|
458
|
+
authenticator: options.authenticator,
|
|
459
|
+
});
|
|
460
|
+
if (!resolution.ok) return { files: [], error: resolution.error };
|
|
461
|
+
let authenticator = resolution.authenticator;
|
|
462
|
+
|
|
463
|
+
let realmRoot = options.realm
|
|
464
|
+
? ensureTrailingSlash(options.realm)
|
|
465
|
+
: undefined;
|
|
466
|
+
if (!realmRoot) {
|
|
467
|
+
try {
|
|
468
|
+
let res = await authenticator.authedRealmFetch(cardUrl, {
|
|
469
|
+
headers: { Accept: CARD_JSON },
|
|
470
|
+
});
|
|
471
|
+
let header = res.headers.get('x-boxel-realm-url');
|
|
472
|
+
if (header) realmRoot = ensureTrailingSlash(header);
|
|
473
|
+
} catch {
|
|
474
|
+
// fall through to the error below
|
|
475
|
+
}
|
|
476
|
+
if (!realmRoot) {
|
|
477
|
+
return {
|
|
478
|
+
files: [],
|
|
479
|
+
error: `Could not determine the source realm for ${cardUrl}. Pass --realm <source-realm-url>.`,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
try {
|
|
485
|
+
let ingester = new RealmCardIngester(
|
|
486
|
+
{
|
|
487
|
+
realmUrl: realmRoot,
|
|
488
|
+
localDir,
|
|
489
|
+
dryRun: options.dryRun,
|
|
490
|
+
cardUrl,
|
|
491
|
+
},
|
|
492
|
+
authenticator,
|
|
493
|
+
pm,
|
|
494
|
+
);
|
|
495
|
+
console.log(
|
|
496
|
+
`Ingesting ${cardUrl}\n from realm ${realmRoot}\n into ${localDir}`,
|
|
497
|
+
);
|
|
498
|
+
await ingester.sync();
|
|
499
|
+
console.log(`\nIngested ${ingester.copiedFiles.length} file(s).`);
|
|
500
|
+
return {
|
|
501
|
+
files: ingester.copiedFiles.sort(),
|
|
502
|
+
error: ingester.hasError
|
|
503
|
+
? 'Ingest completed with errors — some files may be missing.'
|
|
504
|
+
: undefined,
|
|
505
|
+
};
|
|
506
|
+
} catch (error) {
|
|
507
|
+
return {
|
|
508
|
+
files: [],
|
|
509
|
+
error: `Ingest failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export function registerIngestCardCommand(realm: Command): void {
|
|
515
|
+
realm
|
|
516
|
+
.command('ingest-card')
|
|
517
|
+
.description(
|
|
518
|
+
'Copy a card from a source realm into a local directory, bundling the ' +
|
|
519
|
+
"deps that live in the card's own realm: the module, the modules it " +
|
|
520
|
+
'imports from the same realm, its sample instances, and its Catalog ' +
|
|
521
|
+
'Spec. Imports that resolve to the base realm or other realms are ' +
|
|
522
|
+
'left as references (they resolve at runtime). Works across realms; ' +
|
|
523
|
+
'source and target must be on the same realm server.',
|
|
524
|
+
)
|
|
525
|
+
.argument(
|
|
526
|
+
'<source-card-url>',
|
|
527
|
+
'Absolute URL of the source card module (or a card instance) to ingest',
|
|
528
|
+
)
|
|
529
|
+
.argument(
|
|
530
|
+
'<local-dir>',
|
|
531
|
+
'The local directory to write the card + deps into',
|
|
532
|
+
)
|
|
533
|
+
.option(
|
|
534
|
+
'--realm <url>',
|
|
535
|
+
'Source realm URL (defaults to the realm the card belongs to)',
|
|
536
|
+
)
|
|
537
|
+
.option('--dry-run', 'Show what would be copied without writing files')
|
|
538
|
+
.option(
|
|
539
|
+
'--realm-secret-seed',
|
|
540
|
+
'Administrative auth: prompt for a realm secret seed and mint a JWT locally (env: BOXEL_REALM_SECRET_SEED)',
|
|
541
|
+
)
|
|
542
|
+
.action(
|
|
543
|
+
async (
|
|
544
|
+
sourceCardUrl: string,
|
|
545
|
+
localDir: string,
|
|
546
|
+
options: {
|
|
547
|
+
realm?: string;
|
|
548
|
+
dryRun?: boolean;
|
|
549
|
+
realmSecretSeed?: boolean;
|
|
550
|
+
},
|
|
551
|
+
) => {
|
|
552
|
+
let realmSecretSeed = await resolveRealmSecretSeed(
|
|
553
|
+
options.realmSecretSeed === true,
|
|
554
|
+
);
|
|
555
|
+
let result = await ingestCard(sourceCardUrl, localDir, {
|
|
556
|
+
realm: options.realm,
|
|
557
|
+
dryRun: options.dryRun,
|
|
558
|
+
realmSecretSeed,
|
|
559
|
+
});
|
|
560
|
+
if (result.error) {
|
|
561
|
+
console.error(`Error: ${result.error}`);
|
|
562
|
+
process.exit(result.files.length > 0 ? 2 : 1);
|
|
563
|
+
}
|
|
564
|
+
console.log('Ingest completed successfully');
|
|
565
|
+
},
|
|
566
|
+
);
|
|
567
|
+
}
|