@cardstack/boxel-cli 0.9.0 → 0.10.0-unstable.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (995) hide show
  1. package/README.md +12 -0
  2. package/bundled-test-harness/assets/account-switch-failed-GCSVbJML.js +23 -0
  3. package/bundled-test-harness/assets/account-switch-failed-GsWni_Gk.css +18 -0
  4. package/bundled-test-harness/assets/account-switch-failed-test-CdZWNths.js +45 -0
  5. package/bundled-test-harness/assets/add-workspace-c7L50Gx8.js +141 -0
  6. package/bundled-test-harness/assets/add-workspace-test-BZxHa6Pe.js +72 -0
  7. package/bundled-test-harness/assets/advanced-color-picker-0pGF-3WG.js +504 -0
  8. package/bundled-test-harness/assets/advanced-color-picker-pbO4HWc_.js +2 -0
  9. package/bundled-test-harness/assets/ai-assistant-test-Dnm4o9vK.js +2211 -0
  10. package/bundled-test-harness/assets/ai-module-creation-test-C6253CMt.js +151 -0
  11. package/bundled-test-harness/assets/aibot-message-miKyGeKk.js +278 -0
  12. package/bundled-test-harness/assets/app-i8pGdQkw.js +22855 -0
  13. package/bundled-test-harness/assets/app-zC7o6PyQ.css +2718 -0
  14. package/bundled-test-harness/assets/audio-file-def-DHnydP0t.js +133 -0
  15. package/bundled-test-harness/assets/auth-container-BP2gSoo4.css +51 -0
  16. package/bundled-test-harness/assets/auth-container-DN94iVfX.js +24 -0
  17. package/bundled-test-harness/assets/avif-meta-extractor-Bo5zRX1V.js +162 -0
  18. package/bundled-test-harness/assets/base64-image-B0RYxzHT.js +2 -0
  19. package/bundled-test-harness/assets/base64-image-Bxjqdwew.js +262 -0
  20. package/bundled-test-harness/assets/big-integer-7RLj5_7H.js +89 -0
  21. package/bundled-test-harness/assets/big-integer-C9sJxKVy.js +2 -0
  22. package/bundled-test-harness/assets/binary-upload-dedupe-test-DZo3EaV0.js +308 -0
  23. package/bundled-test-harness/assets/boolean-CcKPYUph.js +94 -0
  24. package/bundled-test-harness/assets/boolean-DvsSmtM7.js +2 -0
  25. package/bundled-test-harness/assets/brand-functional-palette-KpVSY2Sa.js +137 -0
  26. package/bundled-test-harness/assets/brand-logo-DDiOec0t.js +295 -0
  27. package/bundled-test-harness/assets/broken-link-template-test-DAngUbFJ.js +192 -0
  28. package/bundled-test-harness/assets/bundled-base-C_lumba6.js +254 -0
  29. package/bundled-test-harness/assets/bundled-base-modules-test-CSF7Rl4Z.js +54 -0
  30. package/bundled-test-harness/assets/buried-stack-item-scroll-test-B0J_EP88.js +236 -0
  31. package/bundled-test-harness/assets/bxl-expression-test-Dej7WgI6.js +250 -0
  32. package/bundled-test-harness/assets/can-invoke-test-elyUcOKT.js +401 -0
  33. package/bundled-test-harness/assets/card-api-CjWXCkqh.js +8 -0
  34. package/bundled-test-harness/assets/card-api-Dzje0smT.js +4393 -0
  35. package/bundled-test-harness/assets/card-api-test-DA8d4Ooc.js +198 -0
  36. package/bundled-test-harness/assets/card-basics-test-mp1Odo-l.js +5364 -0
  37. package/bundled-test-harness/assets/card-chooser-paging-test-y8OfboYd.js +235 -0
  38. package/bundled-test-harness/assets/card-chooser-test-nmg2zkDj.js +393 -0
  39. package/bundled-test-harness/assets/card-collection-BXiO3i7R.js +118 -0
  40. package/bundled-test-harness/assets/card-context-search-results-Dbhn7lvW.js +30 -0
  41. package/bundled-test-harness/assets/card-context-search-results-test-DVXT-YC5.js +184 -0
  42. package/bundled-test-harness/assets/card-def-field-def-relationships-test-mX4rxrtO.js +562 -0
  43. package/bundled-test-harness/assets/card-delete-test-BxFsqFnX.js +466 -0
  44. package/bundled-test-harness/assets/card-error-C-7hjxu9.js +72 -0
  45. package/bundled-test-harness/assets/card-error-awaiting-index-test-BvfY2eaW.js +53 -0
  46. package/bundled-test-harness/assets/card-error-detail-nMwopDir.js +271 -0
  47. package/bundled-test-harness/assets/card-info-CTFxdohf.js +2 -0
  48. package/bundled-test-harness/assets/card-list-B9QrkJ97.js +2 -0
  49. package/bundled-test-harness/assets/card-list-XbwLCXZS.js +202 -0
  50. package/bundled-test-harness/assets/card-resource-JGLjQUy6.js +86 -0
  51. package/bundled-test-harness/assets/cards-grid-CWG41hZE.js +344 -0
  52. package/bundled-test-harness/assets/cards-grid-DSpX99p6.js +2 -0
  53. package/bundled-test-harness/assets/cards-grid-layout-Bht0LwZy.js +2 -0
  54. package/bundled-test-harness/assets/cards-grid-layout-CdpKlHUb.js +111 -0
  55. package/bundled-test-harness/assets/check-correctness-test-C4BrUeKA.js +554 -0
  56. package/bundled-test-harness/assets/clip-BEVvLrXx.js +2 -0
  57. package/bundled-test-harness/assets/clip-CoB714qX.js +92 -0
  58. package/bundled-test-harness/assets/code-ref-C2uguisI.js +2 -0
  59. package/bundled-test-harness/assets/code-ref-Cy7sV5a4.js +138 -0
  60. package/bundled-test-harness/assets/code-submode-availability-test-BsA_Ul01.js +198 -0
  61. package/bundled-test-harness/assets/code-submode-test-DkBhpEPB.js +1839 -0
  62. package/bundled-test-harness/assets/codeblocks-test-B1eZ2_JF.js +418 -0
  63. package/bundled-test-harness/assets/codemirror-editor-C6pxSm5y.js +2 -0
  64. package/bundled-test-harness/assets/codemirror-editor-DzM46Cd8.js +701 -0
  65. package/bundled-test-harness/assets/codemirror-embed-toolbar-test-BemP-ZdG.js +366 -0
  66. package/bundled-test-harness/assets/color-C-jGNFWZ.js +2 -0
  67. package/bundled-test-harness/assets/color-field-test-DPIRaBec.js +212 -0
  68. package/bundled-test-harness/assets/color-picker-field-Bv4IjS-d.js +139 -0
  69. package/bundled-test-harness/assets/color-picker-field-D1bYCQIg.js +2 -0
  70. package/bundled-test-harness/assets/color-wheel-picker-IIaCQplL.js +283 -0
  71. package/bundled-test-harness/assets/color-wheel-picker-Kw-UN3kV.js +2 -0
  72. package/bundled-test-harness/assets/color-zzCBneih.js +65 -0
  73. package/bundled-test-harness/assets/command-data-BMBtjT1E.js +95 -0
  74. package/bundled-test-harness/assets/command-data-BXC5Z0oA.js +2 -0
  75. package/bundled-test-harness/assets/compaction-test-CxUKnxlQ.js +150 -0
  76. package/bundled-test-harness/assets/components-Ct_agx0G.js +14294 -0
  77. package/bundled-test-harness/assets/computed-test-C-lpGQQ3.js +1320 -0
  78. package/bundled-test-harness/assets/container-BdPu8rvc.css +5565 -0
  79. package/bundled-test-harness/assets/container-Dj-5prh9.js +11288 -0
  80. package/bundled-test-harness/assets/contains-many-component-CAWqzX8W.js +2 -0
  81. package/bundled-test-harness/assets/contrast-checker-addon-BTLD7oMx.js +2 -0
  82. package/bundled-test-harness/assets/contrast-checker-addon-DBzizR04.js +71 -0
  83. package/bundled-test-harness/assets/convert-to-class-name-test-zZuKxYvF.js +17 -0
  84. package/bundled-test-harness/assets/coordinate-Bw8va6tO.js +48 -0
  85. package/bundled-test-harness/assets/copy-file-to-realm-test-DtCKPzqj.js +148 -0
  86. package/bundled-test-harness/assets/country-B_tWpLlO.js +199 -0
  87. package/bundled-test-harness/assets/create-file-modal-D-VPyEYp.js +570 -0
  88. package/bundled-test-harness/assets/create-listing-modal-test-hyLkQY0u.js +273 -0
  89. package/bundled-test-harness/assets/create-listing-pr-request-test-rjWFA_5S.js +117 -0
  90. package/bundled-test-harness/assets/create-spec-test-HKIxZGxK.js +256 -0
  91. package/bundled-test-harness/assets/create-specs-9-ELVyJP.js +215 -0
  92. package/bundled-test-harness/assets/create-submission-workflow-test-DNZrbRX8.js +132 -0
  93. package/bundled-test-harness/assets/credential-fields-test-xPEdA911.js +157 -0
  94. package/bundled-test-harness/assets/css-value-Du3HL39X.js +48 -0
  95. package/bundled-test-harness/assets/csv-file-def-EHRmilrp.js +277 -0
  96. package/bundled-test-harness/assets/currency-y6ZCHIqG.js +134 -0
  97. package/bundled-test-harness/assets/date-B27PrSFT.js +183 -0
  98. package/bundled-test-harness/assets/date-CiP5Eb9i.js +2 -0
  99. package/bundled-test-harness/assets/date-time-fields-test-Clf5vxRW.js +359 -0
  100. package/bundled-test-harness/assets/datetime-BEbR9YgU.js +201 -0
  101. package/bundled-test-harness/assets/datetime-DPnrt1wl.js +2 -0
  102. package/bundled-test-harness/assets/datetime-stamp-AuT7F7qn.js +2 -0
  103. package/bundled-test-harness/assets/datetime-stamp-CGwP2P3f.js +81 -0
  104. package/bundled-test-harness/assets/day-BFLxZ9bQ.js +2 -0
  105. package/bundled-test-harness/assets/day-CQoEkqgE.js +113 -0
  106. package/bundled-test-harness/assets/debug-message-test-CzgOpfcI.js +117 -0
  107. package/bundled-test-harness/assets/dist-B-fYvxfL.js +389 -0
  108. package/bundled-test-harness/assets/dist-C2IXvIKX.js +323 -0
  109. package/bundled-test-harness/assets/dist-CdNZu43l.js +1710 -0
  110. package/bundled-test-harness/assets/docx-file-def-BQMw460_.js +60 -0
  111. package/bundled-test-harness/assets/docx-meta-extractor-DBlmH_kV.js +60 -0
  112. package/bundled-test-harness/assets/docx-meta-extractor-Dw4gZ0ae.js +2 -0
  113. package/bundled-test-harness/assets/duration-B0SnEiw1.js +184 -0
  114. package/bundled-test-harness/assets/duration-DbjJTFeA.js +2 -0
  115. package/bundled-test-harness/assets/email-C-8cyWiQ.js +80 -0
  116. package/bundled-test-harness/assets/email-field-test-BOBmvQqx.js +75 -0
  117. package/bundled-test-harness/assets/email-xUgCst-p.js +2 -0
  118. package/bundled-test-harness/assets/enum-BWiCyJlu.js +167 -0
  119. package/bundled-test-harness/assets/enum-CzYjivhO.js +2 -0
  120. package/bundled-test-harness/assets/enum-field-test-Bea9EsQR.js +953 -0
  121. package/bundled-test-harness/assets/error-display-test-Cbl2D_0c.js +343 -0
  122. package/bundled-test-harness/assets/ethereum-address-Bw_J05bD.js +78 -0
  123. package/bundled-test-harness/assets/ethereum-address-C9wHMBt3.js +2 -0
  124. package/bundled-test-harness/assets/expiration-warning-BHcJEjZt.js +90 -0
  125. package/bundled-test-harness/assets/expiration-warning-_G8SKZd0.js +2 -0
  126. package/bundled-test-harness/assets/externals-CKblKBo1.js +4393 -0
  127. package/bundled-test-harness/assets/fallback-banner-BqCrvTDt.js +24 -0
  128. package/bundled-test-harness/assets/fallback-banner-live-delete-test-D_AYMvf6.js +207 -0
  129. package/bundled-test-harness/assets/fallback-banner-test-B8Ne9a5g.js +225 -0
  130. package/bundled-test-harness/assets/fallback-banner-test-C7oaSxd1.js +53 -0
  131. package/bundled-test-harness/assets/fallback-models-test-DY-PvU9k.js +161 -0
  132. package/bundled-test-harness/assets/field-component-Bj8YthPE.js +2 -0
  133. package/bundled-test-harness/assets/field-configuration-test-B5LztQ47.js +548 -0
  134. package/bundled-test-harness/assets/field-edit-Cx_haspD.js +36 -0
  135. package/bundled-test-harness/assets/field-edit-DQZWUz3F.js +2 -0
  136. package/bundled-test-harness/assets/field-markdown-domain-test-DnqK3CrE.js +616 -0
  137. package/bundled-test-harness/assets/field-markdown-oversize-test-BEpbXIvl.js +88 -0
  138. package/bundled-test-harness/assets/field-markdown-primitives-test-BDORWoOk.js +365 -0
  139. package/bundled-test-harness/assets/field-markdown-specialized-test-BmIzadYq.js +534 -0
  140. package/bundled-test-harness/assets/field-test-helpers-CRF9-jFw.js +45 -0
  141. package/bundled-test-harness/assets/file-api-DPMJghBY.js +7 -0
  142. package/bundled-test-harness/assets/file-attachment-test-DFLXg3xV.js +796 -0
  143. package/bundled-test-harness/assets/file-chooser-panel-test-B4DzCWkt.js +153 -0
  144. package/bundled-test-harness/assets/file-chooser-test-DpjOWgpB.js +504 -0
  145. package/bundled-test-harness/assets/file-def-edit-Bstl7Kkl.js +2 -0
  146. package/bundled-test-harness/assets/file-def-edit-C1dzJxmQ.js +26 -0
  147. package/bundled-test-harness/assets/file-def-embedded-CUy4G7Vc.js +2 -0
  148. package/bundled-test-harness/assets/file-def-embedded-DJs6P5t0.js +38 -0
  149. package/bundled-test-harness/assets/file-def-fitted-BlrBFfLh.js +38 -0
  150. package/bundled-test-harness/assets/file-def-fitted-Bo5Qfkyf.js +2 -0
  151. package/bundled-test-harness/assets/file-def-isolated-BsHydanv.js +38 -0
  152. package/bundled-test-harness/assets/file-def-isolated-Dp-Lc99-.js +2 -0
  153. package/bundled-test-harness/assets/file-def-serialization-test-CISKpt_o.js +89 -0
  154. package/bundled-test-harness/assets/file-menu-items-7_ltrFZq.js +117 -0
  155. package/bundled-test-harness/assets/file-menu-items-BnRG9ydE.js +2 -0
  156. package/bundled-test-harness/assets/file-preview-stage-CV3qZpiK.js +72 -0
  157. package/bundled-test-harness/assets/file-preview-stage-DTA5X8rX.js +2 -0
  158. package/bundled-test-harness/assets/file-shell-embedded-BpmiVzIG.js +2 -0
  159. package/bundled-test-harness/assets/file-shell-embedded-CEv0-6OE.js +68 -0
  160. package/bundled-test-harness/assets/file-shell-fitted-C6k3GnMc.js +2 -0
  161. package/bundled-test-harness/assets/file-shell-fitted-iSTg3PJa.js +98 -0
  162. package/bundled-test-harness/assets/file-shell-isolated-C-pEod2J.js +195 -0
  163. package/bundled-test-harness/assets/file-shell-isolated-DI9oU7ix.js +2 -0
  164. package/bundled-test-harness/assets/file-tree-from-index-BtOOMqnb.js +151 -0
  165. package/bundled-test-harness/assets/file-tree-from-index-test-T8w3hPw_.js +96 -0
  166. package/bundled-test-harness/assets/film-5n9_gRqZ.js +4074 -0
  167. package/bundled-test-harness/assets/film-Ca2Vzlfu.js +13 -0
  168. package/bundled-test-harness/assets/film-DEvhBbBu.js +2 -0
  169. package/bundled-test-harness/assets/fitted-6OGuHgoU.js +2 -0
  170. package/bundled-test-harness/assets/fitted-B2l1jlSp.js +34 -0
  171. package/bundled-test-harness/assets/flac-meta-extractor-BoJqvmDC.js +99 -0
  172. package/bundled-test-harness/assets/font-file-def-Czzt5paT.js +64 -0
  173. package/bundled-test-harness/assets/font-meta-extractor-DQYT_e5b.js +2 -0
  174. package/bundled-test-harness/assets/font-meta-extractor-IHD-pG8V.js +303 -0
  175. package/bundled-test-harness/assets/formatted-aibot-message-test-Djsl8RzE.js +109 -0
  176. package/bundled-test-harness/assets/from-elsewhere-BXcLYxxu.js +131 -0
  177. package/bundled-test-harness/assets/frontmatter-field-CciolgL3.js +41 -0
  178. package/bundled-test-harness/assets/garbage-collection-test-BTOLAfB6.js +403 -0
  179. package/bundled-test-harness/assets/gauge-C1loqGq3.js +2 -0
  180. package/bundled-test-harness/assets/gauge-u8dxl90d.js +106 -0
  181. package/bundled-test-harness/assets/general-test-Cd5WtVvd.js +926 -0
  182. package/bundled-test-harness/assets/get-relationship-membership-state-test-DJAuhOVM.js +1308 -0
  183. package/bundled-test-harness/assets/gif-meta-extractor-tSaPtuYW.js +114 -0
  184. package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-DNSy5l59.js +160 -0
  185. package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-B6BbQxYq.js +74 -0
  186. package/bundled-test-harness/assets/helper-m6jA5HmU.js +478 -0
  187. package/bundled-test-harness/assets/host-submode-test-CsgdksBi.js +1243 -0
  188. package/bundled-test-harness/assets/html-file-def-yKtdMSa-.js +82 -0
  189. package/bundled-test-harness/assets/hydratable-card-CxNfbqly.js +147 -0
  190. package/bundled-test-harness/assets/hydratable-card-test-NJ4CI4ey.js +426 -0
  191. package/bundled-test-harness/assets/icons-B3SAtRoj.js +894 -0
  192. package/bundled-test-harness/assets/image-file-def-B0rpS3Yy.js +3 -0
  193. package/bundled-test-harness/assets/image-file-def-DUFmjNL8.js +65 -0
  194. package/bundled-test-harness/assets/image-olOUqgMQ.js +47 -0
  195. package/bundled-test-harness/assets/index-changes-test-D7OE-99k.js +367 -0
  196. package/bundled-test-harness/assets/index-query-engine-test-BBKqgSmg.js +2593 -0
  197. package/bundled-test-harness/assets/inspector-test-DV6Ms2uz.js +1930 -0
  198. package/bundled-test-harness/assets/instance-filter-matcher-test-Bs4kf7E8.js +788 -0
  199. package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DIfgRhIN.js +475 -0
  200. package/bundled-test-harness/assets/interact-submode-setup-D4M_e580.js +566 -0
  201. package/bundled-test-harness/assets/is-component-declaration-test-jPGRTVh1.js +50 -0
  202. package/bundled-test-harness/assets/iso-bmff-DHtkSbQM.js +205 -0
  203. package/bundled-test-harness/assets/iso-bmff-zmOHoSVg.js +2 -0
  204. package/bundled-test-harness/assets/isolated-and-edit-BAnwcK1T.js +2 -0
  205. package/bundled-test-harness/assets/job-priority-header-test-7j2f3Dtl.js +81 -0
  206. package/bundled-test-harness/assets/job-scoped-instance-residency-test-DPzVQUL3.js +103 -0
  207. package/bundled-test-harness/assets/join-the-community-Ft5fjeIA.js +86 -0
  208. package/bundled-test-harness/assets/jpg-meta-extractor-Dsq6rZ8F.js +88 -0
  209. package/bundled-test-harness/assets/json-field-CxOZvp3k.js +19 -0
  210. package/bundled-test-harness/assets/json-field-ojdwGD6T.js +2 -0
  211. package/bundled-test-harness/assets/json-file-def-Da_5-zSM.js +298 -0
  212. package/bundled-test-harness/assets/last-modified-date-BnyJsc04.js +43 -0
  213. package/bundled-test-harness/assets/last-modified-date-test-DFl2mo1B.js +28 -0
  214. package/bundled-test-harness/assets/links-to-editor-DO24-71w.js +2 -0
  215. package/bundled-test-harness/assets/links-to-many-component-C7DabwAY.js +2 -0
  216. package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-D4lDhvnQ.js +398 -0
  217. package/bundled-test-harness/assets/linksto-error-sentinel-test-oWgDz00K.js +238 -0
  218. package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test-CpSl7zJ7.js +354 -0
  219. package/bundled-test-harness/assets/linksto-many-per-slot-access-test-DJY3J8Xl.js +303 -0
  220. package/bundled-test-harness/assets/linksto-sentinel-reload-test-BxzfoONe.js +197 -0
  221. package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test-DyE99km_.js +260 -0
  222. package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-dcWAAgxt.js +196 -0
  223. package/bundled-test-harness/assets/llm-model-DrswiczZ.js +64 -0
  224. package/bundled-test-harness/assets/login-C-EIG0-Q.css +543 -0
  225. package/bundled-test-harness/assets/login-CNeL-9IC.js +408 -0
  226. package/bundled-test-harness/assets/login-error-text-test-CEH2tjNP.js +51 -0
  227. package/bundled-test-harness/assets/login-test-BpMx7qwV.js +246 -0
  228. package/bundled-test-harness/assets/m4a-meta-extractor-BJkMHUIK.js +204 -0
  229. package/bundled-test-harness/assets/main-BaUgfpPE.js +5 -0
  230. package/bundled-test-harness/assets/markdown-ByEGbwov.js +7 -0
  231. package/bundled-test-harness/assets/markdown-KJzgTg-A.js +2 -0
  232. package/bundled-test-harness/assets/markdown-editor-mode-select-BUGPXaSE.js +2 -0
  233. package/bundled-test-harness/assets/markdown-editor-mode-select-DBk8dG0O.js +54 -0
  234. package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-BIlEmna9.js +470 -0
  235. package/bundled-test-harness/assets/markdown-embed-preview-pane-test-B6rscKpk.js +447 -0
  236. package/bundled-test-harness/assets/markdown-embed-preview-test-CTQw1wq-.js +368 -0
  237. package/bundled-test-harness/assets/markdown-fallback-BVsco6gJ.js +2 -0
  238. package/bundled-test-harness/assets/markdown-fallback-test-C_CIFEzH.js +316 -0
  239. package/bundled-test-harness/assets/markdown-highlighting-test-D6YvywF5.js +244 -0
  240. package/bundled-test-harness/assets/markdown-preview-1TSMSUv0.js +64 -0
  241. package/bundled-test-harness/assets/markdown-preview-jbuUjLoD.js +72 -0
  242. package/bundled-test-harness/assets/markdown-preview-test-zuU5uoA_.js +238 -0
  243. package/bundled-test-harness/assets/markdown-skill-frontmatter-test-CoicGRkb.js +146 -0
  244. package/bundled-test-harness/assets/menu-items-DZ_uOoYu.js +2 -0
  245. package/bundled-test-harness/assets/message-tool-test-K6LgTq5d.js +33 -0
  246. package/bundled-test-harness/assets/metadata-fields-WiOuUCDl.js +1415 -0
  247. package/bundled-test-harness/assets/metadata-fields-iu5AfQp3.js +2 -0
  248. package/bundled-test-harness/assets/midi-audio-def-CD2-4Wjx.js +52 -0
  249. package/bundled-test-harness/assets/midi-meta-extractor-CE3sLiEV.js +284 -0
  250. package/bundled-test-harness/assets/midi-meta-extractor-O7c8LHYV.js +2 -0
  251. package/bundled-test-harness/assets/migrate-skill-test-Beh-AeSN.js +161 -0
  252. package/bundled-test-harness/assets/mini-BNXINKKF.js +85 -0
  253. package/bundled-test-harness/assets/mini-C43Q4BWp.js +1519 -0
  254. package/bundled-test-harness/assets/mini-card-chooser-test-B1GMp-31.js +272 -0
  255. package/bundled-test-harness/assets/mini-file-chooser-test-CbI1vrQn.js +201 -0
  256. package/bundled-test-harness/assets/missing-template-BPhJRbDs.js +48 -0
  257. package/bundled-test-harness/assets/missing-template-DP-Pi-HQ.js +2 -0
  258. package/bundled-test-harness/assets/modal-KpPz2f8x.js +322 -0
  259. package/bundled-test-harness/assets/modal-container-0Efz_h2z.js +40 -0
  260. package/bundled-test-harness/assets/model-cost-tier-test-D-5VSjh6.js +173 -0
  261. package/bundled-test-harness/assets/module-contents-service-BRkTETb6.js +256 -0
  262. package/bundled-test-harness/assets/moment-Cln59YUK.js +3474 -0
  263. package/bundled-test-harness/assets/monaco-AbHCoDJY.js +143 -0
  264. package/bundled-test-harness/assets/monaco-test-DCPi18sy.js +100 -0
  265. package/bundled-test-harness/assets/monaco-test-waiter-lvFEYpFj.js +190 -0
  266. package/bundled-test-harness/assets/month-1eUIsvWN.js +2 -0
  267. package/bundled-test-harness/assets/month-BeUdWMWQ.js +123 -0
  268. package/bundled-test-harness/assets/month-day-Bbsd8YbR.js +192 -0
  269. package/bundled-test-harness/assets/month-day-Dks5STJu.js +2 -0
  270. package/bundled-test-harness/assets/month-year-pL_rpUhX.js +2 -0
  271. package/bundled-test-harness/assets/month-year-wH_YnYgL.js +93 -0
  272. package/bundled-test-harness/assets/mp3-meta-extractor-C3u34UHM.js +476 -0
  273. package/bundled-test-harness/assets/mp4-meta-extractor-Bj3F7dxs.js +188 -0
  274. package/bundled-test-harness/assets/multiple-stacks-test-mkNdTUMI.js +208 -0
  275. package/bundled-test-harness/assets/nested-query-field-render-test-BQLn3wg9.js +249 -0
  276. package/bundled-test-harness/assets/no-stacks-test-DpwZQAJ-.js +48 -0
  277. package/bundled-test-harness/assets/number-DZa-fHpu.js +151 -0
  278. package/bundled-test-harness/assets/number-Dvua76YP.js +3 -0
  279. package/bundled-test-harness/assets/number-field-test-BiaH2eaB.js +184 -0
  280. package/bundled-test-harness/assets/number-input-D5nDYDkK.js +82 -0
  281. package/bundled-test-harness/assets/office-extract-JzYva33g.js +27 -0
  282. package/bundled-test-harness/assets/office-extract-XMpsyYRh.js +2 -0
  283. package/bundled-test-harness/assets/ogg-meta-extractor-DJosZ9LA.js +225 -0
  284. package/bundled-test-harness/assets/on-key-BBVkS8Bi.js +472 -0
  285. package/bundled-test-harness/assets/ooxml-BlAE2w4d.js +172 -0
  286. package/bundled-test-harness/assets/ooxml-D-p8OmuM.js +2 -0
  287. package/bundled-test-harness/assets/open-image-in-new-tab-test-DWBU5pw9.js +52 -0
  288. package/bundled-test-harness/assets/operation-lowering-test-nzqprueU.js +2812 -0
  289. package/bundled-test-harness/assets/operations-CPvfTuY3.js +766 -0
  290. package/bundled-test-harness/assets/operations-invocation-test-C75T6zn3.js +523 -0
  291. package/bundled-test-harness/assets/operations-query-test-BoCszQEW.js +459 -0
  292. package/bundled-test-harness/assets/operations-test-79ipSnpM.js +2518 -0
  293. package/bundled-test-harness/assets/operations-x3Aw2Nky.js +3 -0
  294. package/bundled-test-harness/assets/operator-mode-acceptance-test-jjsYtt96.js +1188 -0
  295. package/bundled-test-harness/assets/operator-mode-card-chooser-test-hZP9gEQK.js +1036 -0
  296. package/bundled-test-harness/assets/operator-mode-links-test-DN16SuIx.js +793 -0
  297. package/bundled-test-harness/assets/operator-mode-state-service-gwiTSiWX.js +1275 -0
  298. package/bundled-test-harness/assets/operator-mode-state-service-test-Dt2qnKKP.js +206 -0
  299. package/bundled-test-harness/assets/operator-mode-test-BZnnxO9q.js +683 -0
  300. package/bundled-test-harness/assets/operator-mode-ui-test-O--qEo-y.js +1027 -0
  301. package/bundled-test-harness/assets/overlay-menu-items-test-Bl2k0aAa.js +317 -0
  302. package/bundled-test-harness/assets/overlays-CdN_JokA.js +270 -0
  303. package/bundled-test-harness/assets/overlays-clip-test-DpbR1ZTz.js +91 -0
  304. package/bundled-test-harness/assets/overlays-detached-element-test-cLgEGvMs.js +56 -0
  305. package/bundled-test-harness/assets/pane-PYdezM7g.js +330 -0
  306. package/bundled-test-harness/assets/panel-7FDqkxrr.js +474 -0
  307. package/bundled-test-harness/assets/panel-C3E0s49q.js +3540 -0
  308. package/bundled-test-harness/assets/past-sessions-test-BsjEeoze.js +321 -0
  309. package/bundled-test-harness/assets/patch-fields-test-CsixJmSr.js +1014 -0
  310. package/bundled-test-harness/assets/patch-instance-test-CBDgTi0L.js +348 -0
  311. package/bundled-test-harness/assets/pdf-file-def-9VNjnqDa.js +76 -0
  312. package/bundled-test-harness/assets/pdf-meta-extractor-BF4e5kMR.js +156 -0
  313. package/bundled-test-harness/assets/pdf-meta-extractor-D8Bxh2cc.js +2 -0
  314. package/bundled-test-harness/assets/pdf-viewer-Bu413sN8.js +112 -0
  315. package/bundled-test-harness/assets/pdf-viewer-GKDi_xmf.js +2 -0
  316. package/bundled-test-harness/assets/percentage-TOr6qK2T.js +84 -0
  317. package/bundled-test-harness/assets/permission-checking-realm-test-BRNVYszm.js +306 -0
  318. package/bundled-test-harness/assets/phone-number-D5SR8nWu.js +236 -0
  319. package/bundled-test-harness/assets/phone-number-field-test-DffwtqGd.js +73 -0
  320. package/bundled-test-harness/assets/phone-number-hf_xIVGQ.js +2 -0
  321. package/bundled-test-harness/assets/plate-Vojc88hM.js +41 -0
  322. package/bundled-test-harness/assets/plate-dTUzEMj5.js +2 -0
  323. package/bundled-test-harness/assets/player-CmRw0uM5.js +82 -0
  324. package/bundled-test-harness/assets/player-Dt85lPZl.js +2 -0
  325. package/bundled-test-harness/assets/plural-field-components-test-DNpGuH1D.js +198 -0
  326. package/bundled-test-harness/assets/png-image-def-GY7gjqya.js +48 -0
  327. package/bundled-test-harness/assets/png-meta-extractor-4pI611re.js +2 -0
  328. package/bundled-test-harness/assets/png-meta-extractor-CHp_rpAi.js +111 -0
  329. package/bundled-test-harness/assets/policy-scoped-search-test-CipPu7tY.js +339 -0
  330. package/bundled-test-harness/assets/pptx-file-def-lBBiebvn.js +60 -0
  331. package/bundled-test-harness/assets/pptx-meta-extractor-BjJYWiOJ.js +77 -0
  332. package/bundled-test-harness/assets/pptx-meta-extractor-DbT-dPRg.js +2 -0
  333. package/bundled-test-harness/assets/prerender-persistence-block-test-ClHMVvJt.js +124 -0
  334. package/bundled-test-harness/assets/prerender-serialize-cycle-test-LdqaMTK8.js +134 -0
  335. package/bundled-test-harness/assets/preview-CYlam_aW.js +74 -0
  336. package/bundled-test-harness/assets/preview-format-CiSo4kEa.js +41 -0
  337. package/bundled-test-harness/assets/preview-format-test-MsB1TOLB.js +103 -0
  338. package/bundled-test-harness/assets/process-card-B3xBGkv1.js +2 -0
  339. package/bundled-test-harness/assets/process-card-DumVcx9E.js +114 -0
  340. package/bundled-test-harness/assets/process-card-test-C44H8yVy.js +94 -0
  341. package/bundled-test-harness/assets/profile-settings-modal-ipYzrVTz.js +708 -0
  342. package/bundled-test-harness/assets/progress-circle-DJ6WSO2E.js +95 -0
  343. package/bundled-test-harness/assets/progress-circle-q358_9Sn.js +2 -0
  344. package/bundled-test-harness/assets/quarter-BjO5DlU2.js +2 -0
  345. package/bundled-test-harness/assets/quarter-_D72FwfS.js +168 -0
  346. package/bundled-test-harness/assets/query-field-membership-status-test-CzDyfK49.js +323 -0
  347. package/bundled-test-harness/assets/query-field-page-optin-test-B-x3vsmC.js +126 -0
  348. package/bundled-test-harness/assets/query-field-schema-test-DFw6KuYv.js +231 -0
  349. package/bundled-test-harness/assets/query-field-stale-prerender-test-DSQ-cv_O.js +152 -0
  350. package/bundled-test-harness/assets/query-fields-test-DQiMFRCe.js +535 -0
  351. package/bundled-test-harness/assets/rail-CNspDFyn.js +44 -0
  352. package/bundled-test-harness/assets/rail-D2YcQ0VP.js +2 -0
  353. package/bundled-test-harness/assets/realm-82Z5RUM_.js +95 -0
  354. package/bundled-test-harness/assets/realm-config-SgrwqjRu.js +844 -0
  355. package/bundled-test-harness/assets/realm-config-policy-standing-test-C6sQNk2u.js +290 -0
  356. package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-DcYXBlvi.js +274 -0
  357. package/bundled-test-harness/assets/realm-config-settings-test-DblJv06X.js +187 -0
  358. package/bundled-test-harness/assets/realm-dropdown-CDvL8k3B.js +560 -0
  359. package/bundled-test-harness/assets/realm-et890flh.js +2 -0
  360. package/bundled-test-harness/assets/realm-field-test-pBK_x-Xw.js +100 -0
  361. package/bundled-test-harness/assets/realm-indexing-test-DSFn2F8F.js +4380 -0
  362. package/bundled-test-harness/assets/realm-policy-test-DYnLqzTS.js +1141 -0
  363. package/bundled-test-harness/assets/realm-test-DOZT2EG5.js +2363 -0
  364. package/bundled-test-harness/assets/realm-url-tooltip-qaXTjRb-.js +56 -0
  365. package/bundled-test-harness/assets/realm-url-tooltip-test-DGTEeLH9.js +78 -0
  366. package/bundled-test-harness/assets/reasoning-test-BRkhvYjr.js +234 -0
  367. package/bundled-test-harness/assets/recent-colors-addon-BreXcpg8.js +2 -0
  368. package/bundled-test-harness/assets/recent-colors-addon-CmCkbJ2_.js +61 -0
  369. package/bundled-test-harness/assets/relationship-loading-state-test-B6UGYKzG.js +290 -0
  370. package/bundled-test-harness/assets/relative-time-BjHvL023.js +2 -0
  371. package/bundled-test-harness/assets/relative-time-ChYKOMIM.js +129 -0
  372. package/bundled-test-harness/assets/remix-card-test-CpV0kKfq.js +58 -0
  373. package/bundled-test-harness/assets/rendered-markdown-CJa7IzCC.js +263 -0
  374. package/bundled-test-harness/assets/rendered-markdown-test-CVKsHS4P.js +587 -0
  375. package/bundled-test-harness/assets/resident-instance-reuse-test-jQfW1NMn.js +82 -0
  376. package/bundled-test-harness/assets/response-field-B2-daCl2.js +38 -0
  377. package/bundled-test-harness/assets/result-tile-BSg4mzbc.js +140 -0
  378. package/bundled-test-harness/assets/rich-markdown-BtP1yamM.js +2 -0
  379. package/bundled-test-harness/assets/rich-markdown-C6rQUngb.js +218 -0
  380. package/bundled-test-harness/assets/rich-markdown-field-test-9yB6ykCe.js +1647 -0
  381. package/bundled-test-harness/assets/room-C7tKd02X.js +1008 -0
  382. package/bundled-test-harness/assets/room-message-test-DsMmRYpV.js +445 -0
  383. package/bundled-test-harness/assets/room-test-golI1H61.js +95 -0
  384. package/bundled-test-harness/assets/run-realm-code-CbXk6bnK.js +1600 -0
  385. package/bundled-test-harness/assets/run-realm-code-test-B9JeesaW.js +2468 -0
  386. package/bundled-test-harness/assets/schema-generation-test-uLLGm5Vh.js +28 -0
  387. package/bundled-test-harness/assets/score-BQhCQdUP.js +2 -0
  388. package/bundled-test-harness/assets/score-CoWEzENH.js +100 -0
  389. package/bundled-test-harness/assets/scrolling-test-WHWEkKeZ.js +384 -0
  390. package/bundled-test-harness/assets/search-BkQYpQDY.js +605 -0
  391. package/bundled-test-harness/assets/search-adorn-test-CW92JPOk.js +136 -0
  392. package/bundled-test-harness/assets/search-entries-BU4w6Ymc.js +472 -0
  393. package/bundled-test-harness/assets/search-entries-result-test-9eydsDtD.js +234 -0
  394. package/bundled-test-harness/assets/search-entries-test-ByUREx0G.js +1486 -0
  395. package/bundled-test-harness/assets/search-result-header-UFkdo0Bx.js +128 -0
  396. package/bundled-test-harness/assets/search-results-DrHTuVRZ.js +266 -0
  397. package/bundled-test-harness/assets/search-results-test-krtQQM57.js +578 -0
  398. package/bundled-test-harness/assets/search-selection-menu-test-DoqSbez7.js +108 -0
  399. package/bundled-test-harness/assets/search-sheet-persistence-test-4ZPaEY-y.js +131 -0
  400. package/bundled-test-harness/assets/search-test-BYpq32RM.js +2241 -0
  401. package/bundled-test-harness/assets/searchable-BXw4T11q.js +192 -0
  402. package/bundled-test-harness/assets/searchable-CVvPDA3Q.js +2 -0
  403. package/bundled-test-harness/assets/searchable-option-test-BhLFI4ei.js +322 -0
  404. package/bundled-test-harness/assets/searchable-search-doc-test-DrNLCF73.js +1271 -0
  405. package/bundled-test-harness/assets/secure-sign-in-VNQhe0ae.js +130 -0
  406. package/bundled-test-harness/assets/secure-sign-in-Za8PX9cD.css +24 -0
  407. package/bundled-test-harness/assets/secure-sign-in-aunWHCrB.js +73 -0
  408. package/bundled-test-harness/assets/secure-sign-in-test-BcY1TcNd.js +32 -0
  409. package/bundled-test-harness/assets/secure-sign-in-test-DRdz89BT.js +245 -0
  410. package/bundled-test-harness/assets/sending-test-mbHpGZUu.js +576 -0
  411. package/bundled-test-harness/assets/serialization-rri-form-audit-test-nypV9J82.js +136 -0
  412. package/bundled-test-harness/assets/serialization-test-aLwrFv4d.js +8758 -0
  413. package/bundled-test-harness/assets/setup-Dgn0s6Zk.js +772 -0
  414. package/bundled-test-harness/assets/shared-link-target-reuse-test-D9MR2UNc.js +207 -0
  415. package/bundled-test-harness/assets/show-card-Dwfk332M.js +67 -0
  416. package/bundled-test-harness/assets/show-card-test-CRPwwJvc.js +365 -0
  417. package/bundled-test-harness/assets/show-file-DLdFPHMR.js +34 -0
  418. package/bundled-test-harness/assets/signed-capture-DUR9PohQ.js +204 -0
  419. package/bundled-test-harness/assets/signed-capture-link-test-DfTAB6OT.js +132 -0
  420. package/bundled-test-harness/assets/single-stack-test-Crr_8nti.js +652 -0
  421. package/bundled-test-harness/assets/skill-DQ00VonZ.js +3 -0
  422. package/bundled-test-harness/assets/skill-reference-LEitQV9i.js +112 -0
  423. package/bundled-test-harness/assets/skill-yZXS1VHQ.js +76 -0
  424. package/bundled-test-harness/assets/skills-test-D3-C-Dbm.js +648 -0
  425. package/bundled-test-harness/assets/slider-picker-B6AxKL2j.js +245 -0
  426. package/bundled-test-harness/assets/slider-picker-C4Tc5o-s.js +2 -0
  427. package/bundled-test-harness/assets/spec-Cl_LB6nC.js +602 -0
  428. package/bundled-test-harness/assets/spinner-BHFM7zcR.js +39 -0
  429. package/bundled-test-harness/assets/spinner-DvAvsyDT.css +21 -0
  430. package/bundled-test-harness/assets/store-BV6WX8oV.js +2205 -0
  431. package/bundled-test-harness/assets/store-module-rebuild-test-HyphFJiF.js +454 -0
  432. package/bundled-test-harness/assets/store-search-test-nUeJ5opb.js +175 -0
  433. package/bundled-test-harness/assets/store-test-BebUIJAg.js +3460 -0
  434. package/bundled-test-harness/assets/string-BHZZwNlZ.js +9 -0
  435. package/bundled-test-harness/assets/submode-switcher-D-U9cXo0.js +169 -0
  436. package/bundled-test-harness/assets/svg-meta-extractor-BsG4w2nX.js +42 -0
  437. package/bundled-test-harness/assets/swatches-picker-4vFztxHo.js +33 -0
  438. package/bundled-test-harness/assets/swatches-picker-C7RE7uJ8.js +2 -0
  439. package/bundled-test-harness/assets/switch-submode-CuA0Zfjn.js +79 -0
  440. package/bundled-test-harness/assets/switch-submode-test-i1Qic_Cp.js +168 -0
  441. package/bundled-test-harness/assets/tag-CZNs3DPN.js +105 -0
  442. package/bundled-test-harness/assets/tests-BneuP252.js +3523 -0
  443. package/bundled-test-harness/assets/text-area-DAShQQBe.js +9 -0
  444. package/bundled-test-harness/assets/text-file-def-D2Rs6nS1.js +151 -0
  445. package/bundled-test-harness/assets/text-input-validator-test-C9IG-1GZ.js +156 -0
  446. package/bundled-test-harness/assets/theme-Dm8LWaRK.js +9 -0
  447. package/bundled-test-harness/assets/theme-card-test-Cbb6tAap.js +621 -0
  448. package/bundled-test-harness/assets/theme-scheme-island-test-DOVLakx3.js +264 -0
  449. package/bundled-test-harness/assets/three-d-model-def-DWSPQGgD.js +70 -0
  450. package/bundled-test-harness/assets/time--_Txqya1.js +126 -0
  451. package/bundled-test-harness/assets/time-DKD7Bdjd.js +2 -0
  452. package/bundled-test-harness/assets/time-slots-BZaugjq_.js +2 -0
  453. package/bundled-test-harness/assets/time-slots-C85M0rWl.js +85 -0
  454. package/bundled-test-harness/assets/timeline-B3KGDm3M.js +2 -0
  455. package/bundled-test-harness/assets/timeline-BMwgaZZu.js +59 -0
  456. package/bundled-test-harness/assets/to-device-streaming-test-CMp5bFiz.js +163 -0
  457. package/bundled-test-harness/assets/token-usage-test-CXA0b8Ep.js +166 -0
  458. package/bundled-test-harness/assets/tool-field-BGLelnsr.js +94 -0
  459. package/bundled-test-harness/assets/tool-field-BOFuDDt3.js +2 -0
  460. package/bundled-test-harness/assets/tools-CTjy7Aub.js +725 -0
  461. package/bundled-test-harness/assets/tools-calling-test--JR-7AK7.js +200 -0
  462. package/bundled-test-harness/assets/tools-test-6yAW3W5I.js +2820 -0
  463. package/bundled-test-harness/assets/tools-test-DhpMUQkz.js +1624 -0
  464. package/bundled-test-harness/assets/ts-file-def-CDbf8aw2.js +159 -0
  465. package/bundled-test-harness/assets/update-room-skills-test-DoKsS_1C.js +240 -0
  466. package/bundled-test-harness/assets/url-D0ooeJxC.js +2 -0
  467. package/bundled-test-harness/assets/url-mFskVPSX.js +96 -0
  468. package/bundled-test-harness/assets/video-file-def-AcmWqzev.js +76 -0
  469. package/bundled-test-harness/assets/wav-meta-extractor-CbTLruQf.js +368 -0
  470. package/bundled-test-harness/assets/webm-meta-extractor-C9JH-CMX.js +178 -0
  471. package/bundled-test-harness/assets/webp-meta-extractor-C6sHm4J7.js +98 -0
  472. package/bundled-test-harness/assets/website-Bxuk_OmR.js +92 -0
  473. package/bundled-test-harness/assets/week-Bxssxce7.js +2 -0
  474. package/bundled-test-harness/assets/week-DQLj9974.js +111 -0
  475. package/bundled-test-harness/assets/welcome-to-boxel-BH82RsW5.js +172 -0
  476. package/bundled-test-harness/assets/workspace-DJ_s2x4g.js +614 -0
  477. package/bundled-test-harness/assets/workspace-a11y-test-BJbZNgoP.js +197 -0
  478. package/bundled-test-harness/assets/workspace-behavior-test-BLBARTfb.js +200 -0
  479. package/bundled-test-harness/assets/workspace-chooser-BpmlVrVn.js +2219 -0
  480. package/bundled-test-harness/assets/workspace-chooser-CqLR2Dzh.css +1296 -0
  481. package/bundled-test-harness/assets/workspace-chooser-catalog-order-test-CmAVNAWC.js +36 -0
  482. package/bundled-test-harness/assets/workspace-chooser-unreachable-notice-test-DEfG7Uh9.js +60 -0
  483. package/bundled-test-harness/assets/workspace-delete-multiple-test-DE7Z8ooj.js +212 -0
  484. package/bundled-test-harness/assets/workspace-delete-summary-test-CwtG_zLH.js +63 -0
  485. package/bundled-test-harness/assets/workspace-timestamp-labels-test-DFAaRmJW.js +58 -0
  486. package/bundled-test-harness/assets/xlsx-file-def-DcvaRYnZ.js +60 -0
  487. package/bundled-test-harness/assets/xlsx-meta-extractor-0RlViVaf.js +101 -0
  488. package/bundled-test-harness/assets/xlsx-meta-extractor-BH30Vuem.js +2 -0
  489. package/bundled-test-harness/assets/year-B_MBk_hE.js +78 -0
  490. package/bundled-test-harness/assets/year-hSpccI9L.js +2 -0
  491. package/bundled-test-harness/assets/zip-file-def-c84iddi9.js +288 -0
  492. package/bundled-test-harness/index.html +78 -68
  493. package/bundled-test-harness/tests/index.html +78 -68
  494. package/bundled-types/host-app/components/matrix/account-switch-failed.gts +2 -2
  495. package/bundled-types/host-app/components/matrix/auth.gts +2 -2
  496. package/bundled-types/host-app/components/matrix/cli-auth.gts +7 -6
  497. package/bundled-types/host-app/components/matrix/forgot-password.gts +43 -129
  498. package/bundled-types/host-app/components/matrix/login.gts +15 -118
  499. package/bundled-types/host-app/components/matrix/register-user.gts +45 -226
  500. package/bundled-types/host-app/components/matrix/secure-sign-in.gts +235 -0
  501. package/bundled-types/host-app/components/operator-mode/container.gts +13 -1
  502. package/bundled-types/host-app/components/operator-mode/profile-info-popover.gts +1 -1
  503. package/bundled-types/host-app/config/environment.ts +1 -1
  504. package/bundled-types/host-app/lib/secure-sign-in.ts +130 -0
  505. package/bundled-types/host-app/services/matrix-service.ts +46 -0
  506. package/bundled-types/host-app/services/monaco-service.ts +0 -5
  507. package/bundled-types/host-app/utils/login-token.ts +23 -10
  508. package/dist/api.js +1 -1
  509. package/dist/index.js +289 -285
  510. package/package.json +1 -1
  511. package/src/build-program.ts +6 -2
  512. package/src/commands/profile.ts +72 -3
  513. package/src/lib/profile-manager.ts +5 -1
  514. package/src/lib/secure-session.ts +29 -0
  515. package/src/lib/sso-login.ts +94 -15
  516. package/bundled-test-harness/assets/account-switch-failed-B3pr_iC3.js +0 -32
  517. package/bundled-test-harness/assets/account-switch-failed-DTGZZo-G.css +0 -61
  518. package/bundled-test-harness/assets/account-switch-failed-test-9ENVgvlx.js +0 -45
  519. package/bundled-test-harness/assets/add-workspace-BAbk0250.js +0 -141
  520. package/bundled-test-harness/assets/add-workspace-test-ChAja_t-.js +0 -72
  521. package/bundled-test-harness/assets/advanced-color-picker-C-xBFJ2S.js +0 -504
  522. package/bundled-test-harness/assets/advanced-color-picker-bWAmCT-8.js +0 -2
  523. package/bundled-test-harness/assets/ai-assistant-test-BJ9yetuC.js +0 -2211
  524. package/bundled-test-harness/assets/ai-module-creation-test-Bw3TKS9d.js +0 -151
  525. package/bundled-test-harness/assets/aibot-message-DkgHT6eJ.js +0 -465
  526. package/bundled-test-harness/assets/app-DW5QjtRp.js +0 -22816
  527. package/bundled-test-harness/assets/app-yCDjO4mk.css +0 -2718
  528. package/bundled-test-harness/assets/audio-file-def-bJ3cXVmC.js +0 -133
  529. package/bundled-test-harness/assets/avif-meta-extractor-CrSDfYEt.js +0 -162
  530. package/bundled-test-harness/assets/base64-image-C7UBjK5W.js +0 -262
  531. package/bundled-test-harness/assets/base64-image-CjWpxROT.js +0 -2
  532. package/bundled-test-harness/assets/big-integer-BBql7oGZ.js +0 -89
  533. package/bundled-test-harness/assets/big-integer-B_TrzRy_.js +0 -2
  534. package/bundled-test-harness/assets/binary-upload-dedupe-test-BiX8kS7D.js +0 -308
  535. package/bundled-test-harness/assets/boolean-9LNUUTfw.js +0 -2
  536. package/bundled-test-harness/assets/boolean-BAmK01TF.js +0 -94
  537. package/bundled-test-harness/assets/brand-functional-palette-CFuoS-LS.js +0 -137
  538. package/bundled-test-harness/assets/brand-logo-By89eknI.js +0 -295
  539. package/bundled-test-harness/assets/broken-link-template-test-odBriDSP.js +0 -192
  540. package/bundled-test-harness/assets/bundled-base-CLQkkmN4.js +0 -254
  541. package/bundled-test-harness/assets/bundled-base-modules-test-BYrTaTwa.js +0 -54
  542. package/bundled-test-harness/assets/buried-stack-item-scroll-test-DU4bM5nd.js +0 -236
  543. package/bundled-test-harness/assets/bxl-expression-test-Cs9JaZbC.js +0 -250
  544. package/bundled-test-harness/assets/can-invoke-test-ccMc06BU.js +0 -401
  545. package/bundled-test-harness/assets/card-api-Bn65NUT0.js +0 -8
  546. package/bundled-test-harness/assets/card-api-test-COrFXu2i.js +0 -198
  547. package/bundled-test-harness/assets/card-api-u1pOrwS6.js +0 -4393
  548. package/bundled-test-harness/assets/card-basics-test-D4rn3iN-.js +0 -5364
  549. package/bundled-test-harness/assets/card-chooser-paging-test-bZhdrUXt.js +0 -235
  550. package/bundled-test-harness/assets/card-chooser-test-D9w1duob.js +0 -393
  551. package/bundled-test-harness/assets/card-collection-ClCV-__1.js +0 -118
  552. package/bundled-test-harness/assets/card-context-search-results-H_rN3Upz.js +0 -30
  553. package/bundled-test-harness/assets/card-context-search-results-test-jciyaouV.js +0 -184
  554. package/bundled-test-harness/assets/card-def-field-def-relationships-test-BVZoQzM8.js +0 -562
  555. package/bundled-test-harness/assets/card-delete-test-CuLcZFnY.js +0 -466
  556. package/bundled-test-harness/assets/card-error-DIOivSkD.js +0 -72
  557. package/bundled-test-harness/assets/card-error-awaiting-index-test-JMwcRONq.js +0 -53
  558. package/bundled-test-harness/assets/card-error-detail-96jWBx6B.js +0 -271
  559. package/bundled-test-harness/assets/card-info-BxPtwG1h.js +0 -2
  560. package/bundled-test-harness/assets/card-list-B34qY3io.js +0 -2
  561. package/bundled-test-harness/assets/card-list-BpCaKkZJ.js +0 -202
  562. package/bundled-test-harness/assets/card-resource-DcPbIwH9.js +0 -86
  563. package/bundled-test-harness/assets/cards-grid-CTN8nBT_.js +0 -344
  564. package/bundled-test-harness/assets/cards-grid-Cx44vL-M.js +0 -2
  565. package/bundled-test-harness/assets/cards-grid-layout-BdL0Uzxl.js +0 -111
  566. package/bundled-test-harness/assets/cards-grid-layout-Dn8Yb4ma.js +0 -2
  567. package/bundled-test-harness/assets/check-correctness-test-BfMV-MC0.js +0 -554
  568. package/bundled-test-harness/assets/clip-CK6mVuyN.js +0 -92
  569. package/bundled-test-harness/assets/clip-CfXD1JTr.js +0 -2
  570. package/bundled-test-harness/assets/code-ref-85Bih6Zl.js +0 -138
  571. package/bundled-test-harness/assets/code-ref-DATHaoyt.js +0 -2
  572. package/bundled-test-harness/assets/code-submode-availability-test-DLYlx0wo.js +0 -198
  573. package/bundled-test-harness/assets/code-submode-test-CDIi7MjD.js +0 -1824
  574. package/bundled-test-harness/assets/codeblocks-test-CNPyTvuv.js +0 -418
  575. package/bundled-test-harness/assets/codemirror-editor-BPOPTR-f.js +0 -2
  576. package/bundled-test-harness/assets/codemirror-editor-DPhG0pec.js +0 -701
  577. package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Dk5lFOUq.js +0 -366
  578. package/bundled-test-harness/assets/color-BxN5gRSg.js +0 -65
  579. package/bundled-test-harness/assets/color-CrunRcis.js +0 -2
  580. package/bundled-test-harness/assets/color-field-test-COjFIpXV.js +0 -212
  581. package/bundled-test-harness/assets/color-picker-field-C-GS1CIw.js +0 -139
  582. package/bundled-test-harness/assets/color-picker-field-D3RXhbCK.js +0 -2
  583. package/bundled-test-harness/assets/color-wheel-picker-Bz8cBmf4.js +0 -283
  584. package/bundled-test-harness/assets/color-wheel-picker-DrwPrB8B.js +0 -2
  585. package/bundled-test-harness/assets/command-data-BxXgtNBf.js +0 -2
  586. package/bundled-test-harness/assets/command-data-ZdkcpEgG.js +0 -95
  587. package/bundled-test-harness/assets/compaction-test-DS7DTGT_.js +0 -150
  588. package/bundled-test-harness/assets/components-CbCTWAON.js +0 -17777
  589. package/bundled-test-harness/assets/computed-test-D_OrXDtR.js +0 -1320
  590. package/bundled-test-harness/assets/container-DDolu1gk.js +0 -11109
  591. package/bundled-test-harness/assets/container-DndcCIMv.css +0 -5169
  592. package/bundled-test-harness/assets/contains-many-component-BtgnAXih.js +0 -2
  593. package/bundled-test-harness/assets/contrast-checker-addon-kwtLKWdL.js +0 -2
  594. package/bundled-test-harness/assets/contrast-checker-addon-zFY5cen1.js +0 -71
  595. package/bundled-test-harness/assets/convert-to-class-name-test-BcGWl2K1.js +0 -17
  596. package/bundled-test-harness/assets/coordinate-D72EF1Pl.js +0 -48
  597. package/bundled-test-harness/assets/copy-file-to-realm-test-CYoDX4YV.js +0 -148
  598. package/bundled-test-harness/assets/country-B-iIe5v8.js +0 -199
  599. package/bundled-test-harness/assets/create-file-modal-PpvMksjR.js +0 -570
  600. package/bundled-test-harness/assets/create-listing-modal-test-CQtEf_UD.js +0 -273
  601. package/bundled-test-harness/assets/create-listing-pr-request-test-CDtKWyfk.js +0 -117
  602. package/bundled-test-harness/assets/create-spec-test-Cbqk8I9T.js +0 -256
  603. package/bundled-test-harness/assets/create-specs-CZg2cpnh.js +0 -215
  604. package/bundled-test-harness/assets/create-submission-workflow-test-CYrxF7bg.js +0 -132
  605. package/bundled-test-harness/assets/credential-fields-test-Di4jCJgU.js +0 -157
  606. package/bundled-test-harness/assets/css-value-CceJyI5o.js +0 -48
  607. package/bundled-test-harness/assets/csv-file-def-DJL2aZI9.js +0 -277
  608. package/bundled-test-harness/assets/currency-Bn5WIqzF.js +0 -134
  609. package/bundled-test-harness/assets/date-XI2CVYA2.js +0 -2
  610. package/bundled-test-harness/assets/date-h83UJcFR.js +0 -183
  611. package/bundled-test-harness/assets/date-time-fields-test-Cterr2mj.js +0 -359
  612. package/bundled-test-harness/assets/datetime-DadI80tC.js +0 -201
  613. package/bundled-test-harness/assets/datetime-Dpb_Sejj.js +0 -2
  614. package/bundled-test-harness/assets/datetime-stamp-C4vv397u.js +0 -81
  615. package/bundled-test-harness/assets/datetime-stamp-DIsJdQux.js +0 -2
  616. package/bundled-test-harness/assets/day-C4pZoGNM.js +0 -113
  617. package/bundled-test-harness/assets/day-D0goBhKb.js +0 -2
  618. package/bundled-test-harness/assets/debug-message-test-CV0sj-fl.js +0 -117
  619. package/bundled-test-harness/assets/dist-CAIttNZm.js +0 -1710
  620. package/bundled-test-harness/assets/dist-CLbqnmnm.js +0 -389
  621. package/bundled-test-harness/assets/dist-qkBOmIQy.js +0 -323
  622. package/bundled-test-harness/assets/docx-file-def-hz2tVQKf.js +0 -60
  623. package/bundled-test-harness/assets/docx-meta-extractor-CeRshlxL.js +0 -60
  624. package/bundled-test-harness/assets/docx-meta-extractor-muK5CKF3.js +0 -2
  625. package/bundled-test-harness/assets/duration-BYx1dLfm.js +0 -2
  626. package/bundled-test-harness/assets/duration-FAmTFeUa.js +0 -184
  627. package/bundled-test-harness/assets/email-D-bFy_C1.js +0 -80
  628. package/bundled-test-harness/assets/email-field-test-CY9K2zur.js +0 -75
  629. package/bundled-test-harness/assets/email-j4DZNH2-.js +0 -2
  630. package/bundled-test-harness/assets/enum-B7_baAn_.js +0 -167
  631. package/bundled-test-harness/assets/enum-BQqNzVQS.js +0 -2
  632. package/bundled-test-harness/assets/enum-field-test-BJ9Epz15.js +0 -953
  633. package/bundled-test-harness/assets/error-display-test-CbDWjJ2F.js +0 -343
  634. package/bundled-test-harness/assets/ethereum-address-BOLEnKsm.js +0 -78
  635. package/bundled-test-harness/assets/ethereum-address-s3Kvb2wG.js +0 -2
  636. package/bundled-test-harness/assets/expiration-warning-BaIP1MOZ.js +0 -2
  637. package/bundled-test-harness/assets/expiration-warning-gjEtxPk0.js +0 -90
  638. package/bundled-test-harness/assets/externals-Bih8ejPS.js +0 -4393
  639. package/bundled-test-harness/assets/fallback-banner-MlImHjSD.js +0 -24
  640. package/bundled-test-harness/assets/fallback-banner-live-delete-test-Bm7IKXPf.js +0 -207
  641. package/bundled-test-harness/assets/fallback-banner-test-C7TGA0Ob.js +0 -53
  642. package/bundled-test-harness/assets/fallback-banner-test-lvuaVRXu.js +0 -225
  643. package/bundled-test-harness/assets/fallback-models-test-Dy7iIKUS.js +0 -161
  644. package/bundled-test-harness/assets/field-component-DBoOxTke.js +0 -2
  645. package/bundled-test-harness/assets/field-configuration-test-DnAnzyC-.js +0 -548
  646. package/bundled-test-harness/assets/field-edit-DdJ8Akso.js +0 -2
  647. package/bundled-test-harness/assets/field-edit-XAop92l8.js +0 -36
  648. package/bundled-test-harness/assets/field-markdown-domain-test-cZCqbcjj.js +0 -616
  649. package/bundled-test-harness/assets/field-markdown-oversize-test-BuATetVz.js +0 -88
  650. package/bundled-test-harness/assets/field-markdown-primitives-test-BsubQfhv.js +0 -365
  651. package/bundled-test-harness/assets/field-markdown-specialized-test-4eNLiYpF.js +0 -534
  652. package/bundled-test-harness/assets/field-test-helpers-9I7cHnaU.js +0 -45
  653. package/bundled-test-harness/assets/file-api-CC86I7Er.js +0 -7
  654. package/bundled-test-harness/assets/file-attachment-test-o9191GMb.js +0 -796
  655. package/bundled-test-harness/assets/file-chooser-panel-test-C8aZuJlk.js +0 -153
  656. package/bundled-test-harness/assets/file-chooser-test-B0Tn8CCR.js +0 -504
  657. package/bundled-test-harness/assets/file-def-edit-BSiF2Lje.js +0 -2
  658. package/bundled-test-harness/assets/file-def-edit-C5TYBp_q.js +0 -26
  659. package/bundled-test-harness/assets/file-def-embedded-BLVTCiVB.js +0 -2
  660. package/bundled-test-harness/assets/file-def-embedded-Bep4iD6s.js +0 -38
  661. package/bundled-test-harness/assets/file-def-fitted-BTs-AS78.js +0 -2
  662. package/bundled-test-harness/assets/file-def-fitted-DcPitdYu.js +0 -38
  663. package/bundled-test-harness/assets/file-def-isolated-Kg1YVhm-.js +0 -38
  664. package/bundled-test-harness/assets/file-def-isolated-tK5JWCam.js +0 -2
  665. package/bundled-test-harness/assets/file-def-serialization-test-D4wnd5XK.js +0 -89
  666. package/bundled-test-harness/assets/file-menu-items-CH4-naSK.js +0 -117
  667. package/bundled-test-harness/assets/file-menu-items-emUxx3ZI.js +0 -2
  668. package/bundled-test-harness/assets/file-preview-stage-B1McIWwu.js +0 -2
  669. package/bundled-test-harness/assets/file-preview-stage-BgZLNMN4.js +0 -72
  670. package/bundled-test-harness/assets/file-shell-embedded-BmfuwWfU.js +0 -2
  671. package/bundled-test-harness/assets/file-shell-embedded-zh8CJanA.js +0 -68
  672. package/bundled-test-harness/assets/file-shell-fitted-DSFUNRGJ.js +0 -2
  673. package/bundled-test-harness/assets/file-shell-fitted-DXKDH0fn.js +0 -98
  674. package/bundled-test-harness/assets/file-shell-isolated-0F1MFv4q.js +0 -2
  675. package/bundled-test-harness/assets/file-shell-isolated-DduZZzmi.js +0 -195
  676. package/bundled-test-harness/assets/file-tree-from-index-BzDvvUHy.js +0 -151
  677. package/bundled-test-harness/assets/file-tree-from-index-test-D0hfI4a1.js +0 -96
  678. package/bundled-test-harness/assets/film-BN_HVXBU.js +0 -13
  679. package/bundled-test-harness/assets/film-CKkbUi0L.js +0 -2
  680. package/bundled-test-harness/assets/film-CMNJITZ-.js +0 -4074
  681. package/bundled-test-harness/assets/fitted-CAvdcKpu.js +0 -34
  682. package/bundled-test-harness/assets/fitted-CbKOwd1u.js +0 -2
  683. package/bundled-test-harness/assets/flac-meta-extractor-e8qajPSl.js +0 -99
  684. package/bundled-test-harness/assets/font-file-def-9atde5W8.js +0 -64
  685. package/bundled-test-harness/assets/font-meta-extractor-IralDC8M.js +0 -303
  686. package/bundled-test-harness/assets/font-meta-extractor-zPBVOfoR.js +0 -2
  687. package/bundled-test-harness/assets/formatted-aibot-message-test-CWOiZUng.js +0 -109
  688. package/bundled-test-harness/assets/from-elsewhere-ChxbtsBa.js +0 -131
  689. package/bundled-test-harness/assets/frontmatter-field-cdig7KR9.js +0 -41
  690. package/bundled-test-harness/assets/garbage-collection-test-Dg-ww_Sb.js +0 -403
  691. package/bundled-test-harness/assets/gauge-B45nLOGe.js +0 -106
  692. package/bundled-test-harness/assets/gauge-BK-768BM.js +0 -2
  693. package/bundled-test-harness/assets/general-test-D7cn7PUr.js +0 -926
  694. package/bundled-test-harness/assets/get-relationship-membership-state-test-Skmj9V6y.js +0 -1308
  695. package/bundled-test-harness/assets/gif-meta-extractor-BychhK9q.js +0 -114
  696. package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-C09YUmk4.js +0 -160
  697. package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-DYskx_Kk.js +0 -74
  698. package/bundled-test-harness/assets/helper-BHX0HLF2.js +0 -478
  699. package/bundled-test-harness/assets/host-submode-test-Clw_QnvF.js +0 -1243
  700. package/bundled-test-harness/assets/html-file-def-C0P9giwU.js +0 -82
  701. package/bundled-test-harness/assets/hydratable-card-DnjrxKsT.js +0 -147
  702. package/bundled-test-harness/assets/hydratable-card-test-BAmWHfv1.js +0 -426
  703. package/bundled-test-harness/assets/icons-DBXBZgLe.js +0 -894
  704. package/bundled-test-harness/assets/image-Cip6ojDd.js +0 -47
  705. package/bundled-test-harness/assets/image-file-def-BdQxjZcN.js +0 -65
  706. package/bundled-test-harness/assets/image-file-def-DP4aqWcS.js +0 -3
  707. package/bundled-test-harness/assets/index-changes-test-D8b_56Ke.js +0 -367
  708. package/bundled-test-harness/assets/index-query-engine-test-CCyaUwMX.js +0 -2593
  709. package/bundled-test-harness/assets/inspector-test-BJTVGdOO.js +0 -1930
  710. package/bundled-test-harness/assets/instance-filter-matcher-test-DjsPrXL7.js +0 -788
  711. package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DSqM0vxh.js +0 -475
  712. package/bundled-test-harness/assets/interact-submode-setup-DF31UMX-.js +0 -566
  713. package/bundled-test-harness/assets/is-component-declaration-test-Did47eG9.js +0 -50
  714. package/bundled-test-harness/assets/iso-bmff-LuWkGL__.js +0 -205
  715. package/bundled-test-harness/assets/iso-bmff-_flO6c20.js +0 -2
  716. package/bundled-test-harness/assets/isolated-and-edit-frocLHin.js +0 -2
  717. package/bundled-test-harness/assets/job-priority-header-test-DHLAXfp7.js +0 -81
  718. package/bundled-test-harness/assets/job-scoped-instance-residency-test-C1Bt5j98.js +0 -103
  719. package/bundled-test-harness/assets/join-the-community-BBUSO2cs.js +0 -86
  720. package/bundled-test-harness/assets/jpg-meta-extractor-CoybO4Hq.js +0 -88
  721. package/bundled-test-harness/assets/json-field-8sdH5RQb.js +0 -2
  722. package/bundled-test-harness/assets/json-field-BDD3iTUh.js +0 -19
  723. package/bundled-test-harness/assets/json-file-def-BKibsfc6.js +0 -298
  724. package/bundled-test-harness/assets/last-modified-date-CR5jru2m.js +0 -43
  725. package/bundled-test-harness/assets/last-modified-date-test-jJ00YdTm.js +0 -28
  726. package/bundled-test-harness/assets/links-to-editor-rDoCYaN-.js +0 -2
  727. package/bundled-test-harness/assets/links-to-many-component-BqZT88Fb.js +0 -2
  728. package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-Cp1Eb_4U.js +0 -398
  729. package/bundled-test-harness/assets/linksto-error-sentinel-test-Bddavnh_.js +0 -238
  730. package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test-c5WegXnR.js +0 -354
  731. package/bundled-test-harness/assets/linksto-many-per-slot-access-test-CWskzfGW.js +0 -303
  732. package/bundled-test-harness/assets/linksto-sentinel-reload-test-ByeVNhr8.js +0 -197
  733. package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test-DP26i6Gb.js +0 -260
  734. package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-fDUXx8tO.js +0 -196
  735. package/bundled-test-harness/assets/llm-model-BcLEkTV7.js +0 -64
  736. package/bundled-test-harness/assets/login-CeuuNVvU.css +0 -139
  737. package/bundled-test-harness/assets/login-DV0WlJv-.js +0 -348
  738. package/bundled-test-harness/assets/login-error-text-test-BMGY_9gW.js +0 -51
  739. package/bundled-test-harness/assets/login-test-CL9YpMH5.js +0 -246
  740. package/bundled-test-harness/assets/m4a-meta-extractor-CHO1JQtb.js +0 -204
  741. package/bundled-test-harness/assets/main-CPLT8JNu.js +0 -5
  742. package/bundled-test-harness/assets/markdown-BvBALLGh.js +0 -7
  743. package/bundled-test-harness/assets/markdown-DFezmrFD.js +0 -2
  744. package/bundled-test-harness/assets/markdown-editor-mode-select-Au64bcIO.js +0 -2
  745. package/bundled-test-harness/assets/markdown-editor-mode-select-rK9PP8rv.js +0 -54
  746. package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-CIxizf5k.js +0 -470
  747. package/bundled-test-harness/assets/markdown-embed-preview-pane-test-C7GoNN7l.js +0 -447
  748. package/bundled-test-harness/assets/markdown-embed-preview-test-CDnj4uhd.js +0 -368
  749. package/bundled-test-harness/assets/markdown-fallback-n7PsLNmO.js +0 -2
  750. package/bundled-test-harness/assets/markdown-fallback-test-DTHT6OwQ.js +0 -316
  751. package/bundled-test-harness/assets/markdown-highlighting-test-DJ-4WSE_.js +0 -244
  752. package/bundled-test-harness/assets/markdown-preview-Ccelx5W-.js +0 -64
  753. package/bundled-test-harness/assets/markdown-preview-JXuMC_ve.js +0 -72
  754. package/bundled-test-harness/assets/markdown-preview-test-ByZqrpPk.js +0 -238
  755. package/bundled-test-harness/assets/markdown-skill-frontmatter-test-DAHGeL4K.js +0 -146
  756. package/bundled-test-harness/assets/menu-items-DzJm9H_H.js +0 -2
  757. package/bundled-test-harness/assets/message-tool-test-lmdrIEdY.js +0 -33
  758. package/bundled-test-harness/assets/metadata-fields-BZZr4Qe5.js +0 -2
  759. package/bundled-test-harness/assets/metadata-fields-BtdjGsKE.js +0 -1415
  760. package/bundled-test-harness/assets/midi-audio-def-uYbYFmFi.js +0 -52
  761. package/bundled-test-harness/assets/midi-meta-extractor-DNI5gc1q.js +0 -284
  762. package/bundled-test-harness/assets/midi-meta-extractor-DbKZ4fMG.js +0 -2
  763. package/bundled-test-harness/assets/migrate-skill-test-DI1xceiL.js +0 -161
  764. package/bundled-test-harness/assets/mini-CNoDyHqG.js +0 -1519
  765. package/bundled-test-harness/assets/mini-DexlIeKK.js +0 -85
  766. package/bundled-test-harness/assets/mini-card-chooser-test-DT5eIf1_.js +0 -272
  767. package/bundled-test-harness/assets/mini-file-chooser-test-DTQnKTZJ.js +0 -201
  768. package/bundled-test-harness/assets/missing-template-DL2mwddM.js +0 -2
  769. package/bundled-test-harness/assets/missing-template-ltqlJ4JC.js +0 -48
  770. package/bundled-test-harness/assets/modal-container-DRnt95-S.js +0 -40
  771. package/bundled-test-harness/assets/modal-zE95eEFp.js +0 -322
  772. package/bundled-test-harness/assets/model-cost-tier-test-CcFz7hcv.js +0 -173
  773. package/bundled-test-harness/assets/module-contents-service-Dk_zWt-V.js +0 -256
  774. package/bundled-test-harness/assets/month-BqReBYWo.js +0 -2
  775. package/bundled-test-harness/assets/month-RhvmIp40.js +0 -123
  776. package/bundled-test-harness/assets/month-day-XFAQA72z.js +0 -2
  777. package/bundled-test-harness/assets/month-day-XzKpk6nz.js +0 -192
  778. package/bundled-test-harness/assets/month-year-BeuNr2Cl.js +0 -2
  779. package/bundled-test-harness/assets/month-year-DhU7hATV.js +0 -93
  780. package/bundled-test-harness/assets/mp3-meta-extractor-Dx2RnJc5.js +0 -476
  781. package/bundled-test-harness/assets/mp4-meta-extractor--k0m8KsT.js +0 -188
  782. package/bundled-test-harness/assets/multiple-stacks-test-bC24IWcJ.js +0 -208
  783. package/bundled-test-harness/assets/nested-query-field-render-test-qxElXx1e.js +0 -249
  784. package/bundled-test-harness/assets/no-stacks-test-Br7IGAgV.js +0 -48
  785. package/bundled-test-harness/assets/number-73SsCMEF.js +0 -3
  786. package/bundled-test-harness/assets/number-CicTBWQd.js +0 -151
  787. package/bundled-test-harness/assets/number-field-test-kV5zXo1J.js +0 -184
  788. package/bundled-test-harness/assets/number-input-CQy4xUeA.js +0 -82
  789. package/bundled-test-harness/assets/office-extract-Bo8sbNkK.js +0 -27
  790. package/bundled-test-harness/assets/office-extract-CfBaoRMD.js +0 -2
  791. package/bundled-test-harness/assets/ogg-meta-extractor-aIf5q_Rq.js +0 -225
  792. package/bundled-test-harness/assets/on-key-C8acaldQ.js +0 -472
  793. package/bundled-test-harness/assets/ooxml-Bu3iZezv.js +0 -172
  794. package/bundled-test-harness/assets/ooxml-jQPBQK25.js +0 -2
  795. package/bundled-test-harness/assets/open-image-in-new-tab-test-CP7q3kMm.js +0 -52
  796. package/bundled-test-harness/assets/operation-lowering-test-9Mdr0hRT.js +0 -2812
  797. package/bundled-test-harness/assets/operations-R9b661Qn.js +0 -3
  798. package/bundled-test-harness/assets/operations-Zv_V3Api.js +0 -766
  799. package/bundled-test-harness/assets/operations-invocation-test-BJPpWb2H.js +0 -523
  800. package/bundled-test-harness/assets/operations-query-test-DufdmPQF.js +0 -459
  801. package/bundled-test-harness/assets/operations-test-CzT051YH.js +0 -2518
  802. package/bundled-test-harness/assets/operator-mode-acceptance-test-ByOIOcD0.js +0 -1188
  803. package/bundled-test-harness/assets/operator-mode-card-chooser-test-CNhR9mvv.js +0 -1036
  804. package/bundled-test-harness/assets/operator-mode-links-test-CuxSVTPR.js +0 -793
  805. package/bundled-test-harness/assets/operator-mode-state-service-CCeHt5SH.js +0 -1275
  806. package/bundled-test-harness/assets/operator-mode-state-service-test-C8TI9WWg.js +0 -206
  807. package/bundled-test-harness/assets/operator-mode-test-DG-mG8Tn.js +0 -683
  808. package/bundled-test-harness/assets/operator-mode-ui-test-DB7xhjS0.js +0 -1027
  809. package/bundled-test-harness/assets/overlay-menu-items-test-C6rcdF_S.js +0 -317
  810. package/bundled-test-harness/assets/overlays-D2zmPxzK.js +0 -270
  811. package/bundled-test-harness/assets/overlays-clip-test-Clpq3JzQ.js +0 -91
  812. package/bundled-test-harness/assets/overlays-detached-element-test-BtsTeJch.js +0 -56
  813. package/bundled-test-harness/assets/pane-f-IYhcWT.js +0 -330
  814. package/bundled-test-harness/assets/panel-B3PCSBbf.js +0 -3540
  815. package/bundled-test-harness/assets/panel-Ban7zCBP.js +0 -474
  816. package/bundled-test-harness/assets/past-sessions-test-uM2m-oKV.js +0 -321
  817. package/bundled-test-harness/assets/patch-fields-test-COPjDhnt.js +0 -1014
  818. package/bundled-test-harness/assets/patch-instance-test-CRb3dfby.js +0 -348
  819. package/bundled-test-harness/assets/pdf-file-def-J_yOUU8_.js +0 -76
  820. package/bundled-test-harness/assets/pdf-meta-extractor-83T5Bdo7.js +0 -156
  821. package/bundled-test-harness/assets/pdf-meta-extractor-INFIklMy.js +0 -2
  822. package/bundled-test-harness/assets/pdf-viewer-B4rRluWA.js +0 -2
  823. package/bundled-test-harness/assets/pdf-viewer-vYem8ozk.js +0 -112
  824. package/bundled-test-harness/assets/percentage-ChagfNRG.js +0 -84
  825. package/bundled-test-harness/assets/permission-checking-realm-test-Dmb2a428.js +0 -306
  826. package/bundled-test-harness/assets/phone-number-BiD2eaSd.js +0 -236
  827. package/bundled-test-harness/assets/phone-number-C-wt4_UK.js +0 -2
  828. package/bundled-test-harness/assets/phone-number-field-test-BHzAmuBP.js +0 -73
  829. package/bundled-test-harness/assets/plate-CqN2nM6P.js +0 -41
  830. package/bundled-test-harness/assets/plate-DaIfpORN.js +0 -2
  831. package/bundled-test-harness/assets/player-CGt5fTd5.js +0 -2
  832. package/bundled-test-harness/assets/player-CN0l44LK.js +0 -82
  833. package/bundled-test-harness/assets/plural-field-components-test-CO2g2opW.js +0 -198
  834. package/bundled-test-harness/assets/png-image-def-B_oou2wS.js +0 -48
  835. package/bundled-test-harness/assets/png-meta-extractor-BfPz1qP_.js +0 -2
  836. package/bundled-test-harness/assets/png-meta-extractor-C8ai8sPw.js +0 -111
  837. package/bundled-test-harness/assets/policy-scoped-search-test-BRRp2a1A.js +0 -339
  838. package/bundled-test-harness/assets/pptx-file-def-C3qYEHDM.js +0 -60
  839. package/bundled-test-harness/assets/pptx-meta-extractor-8IuoBq4I.js +0 -77
  840. package/bundled-test-harness/assets/pptx-meta-extractor-BPhy9RMM.js +0 -2
  841. package/bundled-test-harness/assets/prerender-persistence-block-test-Cteb_Rs_.js +0 -124
  842. package/bundled-test-harness/assets/prerender-serialize-cycle-test-CH7b6Ra9.js +0 -134
  843. package/bundled-test-harness/assets/preview-CmERZpI6.js +0 -74
  844. package/bundled-test-harness/assets/preview-format-BPMlCSbb.js +0 -41
  845. package/bundled-test-harness/assets/preview-format-test-B7sA8fbZ.js +0 -103
  846. package/bundled-test-harness/assets/process-card-CtDzDB-_.js +0 -2
  847. package/bundled-test-harness/assets/process-card-erbWKY5h.js +0 -114
  848. package/bundled-test-harness/assets/process-card-test-DXOt1jDW.js +0 -94
  849. package/bundled-test-harness/assets/profile-settings-modal-11BrR058.js +0 -708
  850. package/bundled-test-harness/assets/progress-circle-Cd79Zqh2.js +0 -2
  851. package/bundled-test-harness/assets/progress-circle-sc-W5aUl.js +0 -95
  852. package/bundled-test-harness/assets/quarter-B61kCpcD.js +0 -168
  853. package/bundled-test-harness/assets/quarter-d5jkTzcz.js +0 -2
  854. package/bundled-test-harness/assets/query-field-membership-status-test-BmpVfohw.js +0 -323
  855. package/bundled-test-harness/assets/query-field-page-optin-test-9_Cce-OJ.js +0 -126
  856. package/bundled-test-harness/assets/query-field-schema-test-CwV7xanX.js +0 -231
  857. package/bundled-test-harness/assets/query-field-stale-prerender-test-RkdnZ-VV.js +0 -152
  858. package/bundled-test-harness/assets/query-fields-test-BLxYkTAM.js +0 -535
  859. package/bundled-test-harness/assets/rail-CFPU0tFe.js +0 -2
  860. package/bundled-test-harness/assets/rail-CQ53Dakr.js +0 -44
  861. package/bundled-test-harness/assets/realm-DdVH9lSZ.js +0 -95
  862. package/bundled-test-harness/assets/realm-DdsFw3b-.js +0 -2
  863. package/bundled-test-harness/assets/realm-config-DIslxoB7.js +0 -844
  864. package/bundled-test-harness/assets/realm-config-policy-standing-test-b4WxNDor.js +0 -290
  865. package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-C-rcvkkD.js +0 -274
  866. package/bundled-test-harness/assets/realm-config-settings-test-DDUkM3zw.js +0 -187
  867. package/bundled-test-harness/assets/realm-dropdown-1j55Dy-1.js +0 -560
  868. package/bundled-test-harness/assets/realm-field-test-D-uEtFKO.js +0 -100
  869. package/bundled-test-harness/assets/realm-indexing-test-U9m0epR-.js +0 -4380
  870. package/bundled-test-harness/assets/realm-policy-test-DhKabhlk.js +0 -1141
  871. package/bundled-test-harness/assets/realm-test-BX6C9SS5.js +0 -2363
  872. package/bundled-test-harness/assets/realm-url-tooltip-BjjcKqBx.js +0 -56
  873. package/bundled-test-harness/assets/realm-url-tooltip-test-DW0ZwEEE.js +0 -78
  874. package/bundled-test-harness/assets/reasoning-test-BWT94KXG.js +0 -234
  875. package/bundled-test-harness/assets/recent-colors-addon-CfgmgilF.js +0 -61
  876. package/bundled-test-harness/assets/recent-colors-addon-D--Ry3Pf.js +0 -2
  877. package/bundled-test-harness/assets/relationship-loading-state-test-C5R6jao_.js +0 -290
  878. package/bundled-test-harness/assets/relative-time-Bq7pqums.js +0 -2
  879. package/bundled-test-harness/assets/relative-time-D0QyW4ig.js +0 -129
  880. package/bundled-test-harness/assets/remix-card-test-Cy0h3Xdf.js +0 -58
  881. package/bundled-test-harness/assets/rendered-markdown-Hw_EF8SO.js +0 -263
  882. package/bundled-test-harness/assets/rendered-markdown-test-CqeF-UZd.js +0 -587
  883. package/bundled-test-harness/assets/resident-instance-reuse-test-BiI6L40n.js +0 -82
  884. package/bundled-test-harness/assets/response-field-BCxG5phG.js +0 -38
  885. package/bundled-test-harness/assets/result-tile-DMzRnTP8.js +0 -140
  886. package/bundled-test-harness/assets/rich-markdown-C4RUl7L0.js +0 -2
  887. package/bundled-test-harness/assets/rich-markdown-DxQSCg-o.js +0 -218
  888. package/bundled-test-harness/assets/rich-markdown-field-test-B7wpedKs.js +0 -1647
  889. package/bundled-test-harness/assets/room-D0M0Zwrs.js +0 -1008
  890. package/bundled-test-harness/assets/room-message-test-BWWd4xC8.js +0 -445
  891. package/bundled-test-harness/assets/room-test-DFH-nOwi.js +0 -95
  892. package/bundled-test-harness/assets/run-realm-code-DyVyEDBl.js +0 -1600
  893. package/bundled-test-harness/assets/run-realm-code-test-BpxF-tOz.js +0 -2468
  894. package/bundled-test-harness/assets/schema-generation-test-DjaJqpYP.js +0 -28
  895. package/bundled-test-harness/assets/score-Cfp34BE7.js +0 -2
  896. package/bundled-test-harness/assets/score-DIWWpeyf.js +0 -100
  897. package/bundled-test-harness/assets/scrolling-test-hA_uBwBg.js +0 -384
  898. package/bundled-test-harness/assets/search-C0-b7dJI.js +0 -605
  899. package/bundled-test-harness/assets/search-adorn-test-C6KP3AwA.js +0 -136
  900. package/bundled-test-harness/assets/search-entries-BfPq5sPS.js +0 -472
  901. package/bundled-test-harness/assets/search-entries-result-test-Bl9u_BOD.js +0 -234
  902. package/bundled-test-harness/assets/search-entries-test-BDC_lS43.js +0 -1486
  903. package/bundled-test-harness/assets/search-result-header-DCAze_cg.js +0 -128
  904. package/bundled-test-harness/assets/search-results-Dd0enVun.js +0 -266
  905. package/bundled-test-harness/assets/search-results-test-T5KEEII4.js +0 -578
  906. package/bundled-test-harness/assets/search-selection-menu-test-CCssnBq1.js +0 -108
  907. package/bundled-test-harness/assets/search-sheet-persistence-test-BzQiO-FK.js +0 -131
  908. package/bundled-test-harness/assets/search-test-fyCWb24m.js +0 -2241
  909. package/bundled-test-harness/assets/searchable-BkgeKQMl.js +0 -2
  910. package/bundled-test-harness/assets/searchable-D_6p6fyb.js +0 -192
  911. package/bundled-test-harness/assets/searchable-option-test-CnCUYGaq.js +0 -322
  912. package/bundled-test-harness/assets/searchable-search-doc-test-B8Q0D98v.js +0 -1271
  913. package/bundled-test-harness/assets/sending-test-D5PGBDys.js +0 -576
  914. package/bundled-test-harness/assets/serialization-rri-form-audit-test-BRJ1cJ31.js +0 -136
  915. package/bundled-test-harness/assets/serialization-test-DM6hK258.js +0 -8758
  916. package/bundled-test-harness/assets/setup-C_GgVgzM.js +0 -772
  917. package/bundled-test-harness/assets/shared-link-target-reuse-test-Be-lSKib.js +0 -207
  918. package/bundled-test-harness/assets/show-card-BFG6KR1m.js +0 -67
  919. package/bundled-test-harness/assets/show-card-test-l0wMrfZq.js +0 -365
  920. package/bundled-test-harness/assets/show-file-B8-FRVHj.js +0 -34
  921. package/bundled-test-harness/assets/signed-capture-D_Q44TQ7.js +0 -204
  922. package/bundled-test-harness/assets/signed-capture-link-test-DOS5xpYv.js +0 -132
  923. package/bundled-test-harness/assets/single-stack-test-BIEtzHVS.js +0 -652
  924. package/bundled-test-harness/assets/skill-BUTGmSsm.js +0 -76
  925. package/bundled-test-harness/assets/skill-Bo7R_2Ud.js +0 -3
  926. package/bundled-test-harness/assets/skill-reference-Cs64py3k.js +0 -112
  927. package/bundled-test-harness/assets/skills-test-CXxSIkYa.js +0 -648
  928. package/bundled-test-harness/assets/slider-picker-C81errGI.js +0 -245
  929. package/bundled-test-harness/assets/slider-picker-mvKsy6cR.js +0 -2
  930. package/bundled-test-harness/assets/spec-B55lJurX.js +0 -602
  931. package/bundled-test-harness/assets/store-DyQ0KiyI.js +0 -2205
  932. package/bundled-test-harness/assets/store-module-rebuild-test-C7532_bS.js +0 -454
  933. package/bundled-test-harness/assets/store-search-test-80NMJuoW.js +0 -175
  934. package/bundled-test-harness/assets/store-test-dHiWXXMs.js +0 -3460
  935. package/bundled-test-harness/assets/string-DHlQEHYm.js +0 -9
  936. package/bundled-test-harness/assets/submode-switcher-DQv-CD6G.js +0 -169
  937. package/bundled-test-harness/assets/svg-meta-extractor-Uw_EJytF.js +0 -42
  938. package/bundled-test-harness/assets/swatches-picker-CaEoibN1.js +0 -33
  939. package/bundled-test-harness/assets/swatches-picker-gPl50JbP.js +0 -2
  940. package/bundled-test-harness/assets/switch-submode-BKDnJd4m.js +0 -79
  941. package/bundled-test-harness/assets/switch-submode-test-_E2mVk4z.js +0 -168
  942. package/bundled-test-harness/assets/tag-B60lDr-j.js +0 -105
  943. package/bundled-test-harness/assets/tests-BBBgPBB6.js +0 -3520
  944. package/bundled-test-harness/assets/text-area-CJjWmwpi.js +0 -9
  945. package/bundled-test-harness/assets/text-file-def-u_dl0i2z.js +0 -151
  946. package/bundled-test-harness/assets/text-input-validator-test-BTwnkSS2.js +0 -156
  947. package/bundled-test-harness/assets/theme-BK-fAHVn.js +0 -9
  948. package/bundled-test-harness/assets/theme-card-test-BQmT7rqr.js +0 -621
  949. package/bundled-test-harness/assets/theme-scheme-island-test-Oi3aeyp1.js +0 -264
  950. package/bundled-test-harness/assets/three-d-model-def-B4KckPVC.js +0 -70
  951. package/bundled-test-harness/assets/time-BcuaSkHg.js +0 -126
  952. package/bundled-test-harness/assets/time-f7Irg7Z7.js +0 -2
  953. package/bundled-test-harness/assets/time-slots-ClYIZN53.js +0 -2
  954. package/bundled-test-harness/assets/time-slots-TI1aaqRN.js +0 -85
  955. package/bundled-test-harness/assets/timeline-Cof9eyq0.js +0 -59
  956. package/bundled-test-harness/assets/timeline-DFWQtCWE.js +0 -2
  957. package/bundled-test-harness/assets/to-device-streaming-test-BDrUUlOt.js +0 -163
  958. package/bundled-test-harness/assets/token-usage-test-CiZo03fY.js +0 -166
  959. package/bundled-test-harness/assets/tool-field-BXHr9r0w.js +0 -94
  960. package/bundled-test-harness/assets/tool-field-CoRO5C4R.js +0 -2
  961. package/bundled-test-harness/assets/tools-CmVaYDIS.js +0 -725
  962. package/bundled-test-harness/assets/tools-calling-test-B454__XF.js +0 -200
  963. package/bundled-test-harness/assets/tools-test-CLu51dJO.js +0 -1624
  964. package/bundled-test-harness/assets/tools-test-XGRAvVug.js +0 -2820
  965. package/bundled-test-harness/assets/ts-file-def-C05BDwdg.js +0 -159
  966. package/bundled-test-harness/assets/update-room-skills-test-jOvP14JX.js +0 -240
  967. package/bundled-test-harness/assets/url-BFf2CNo-.js +0 -2
  968. package/bundled-test-harness/assets/url-CYm-CeXp.js +0 -96
  969. package/bundled-test-harness/assets/video-file-def-B2UIrOFS.js +0 -76
  970. package/bundled-test-harness/assets/wav-meta-extractor-BNkv7e2f.js +0 -368
  971. package/bundled-test-harness/assets/webm-meta-extractor-C933kYyc.js +0 -178
  972. package/bundled-test-harness/assets/webp-meta-extractor-BLz0z1pZ.js +0 -98
  973. package/bundled-test-harness/assets/website-BuOMUW1v.js +0 -92
  974. package/bundled-test-harness/assets/week-Bo0666ji.js +0 -111
  975. package/bundled-test-harness/assets/week-CaVFA8Vc.js +0 -2
  976. package/bundled-test-harness/assets/welcome-to-boxel-PWard7GF.js +0 -172
  977. package/bundled-test-harness/assets/workspace-KXfFTQNV.js +0 -614
  978. package/bundled-test-harness/assets/workspace-a11y-test-Buwb-rfO.js +0 -197
  979. package/bundled-test-harness/assets/workspace-behavior-test-CbgFUOOo.js +0 -200
  980. package/bundled-test-harness/assets/workspace-chooser-BmQvhhrl.js +0 -2248
  981. package/bundled-test-harness/assets/workspace-chooser-Cu84Gd_E.css +0 -1317
  982. package/bundled-test-harness/assets/workspace-chooser-catalog-order-test-rcRw6sni.js +0 -36
  983. package/bundled-test-harness/assets/workspace-chooser-unreachable-notice-test-DUXnBIdY.js +0 -60
  984. package/bundled-test-harness/assets/workspace-delete-multiple-test-DjRKhZ2g.js +0 -212
  985. package/bundled-test-harness/assets/workspace-delete-summary-test-CvkLVYyN.js +0 -63
  986. package/bundled-test-harness/assets/workspace-timestamp-labels-test-AYJT4inv.js +0 -58
  987. package/bundled-test-harness/assets/xlsx-file-def-DuKdbGrJ.js +0 -60
  988. package/bundled-test-harness/assets/xlsx-meta-extractor-Bz-C2JWP.js +0 -101
  989. package/bundled-test-harness/assets/xlsx-meta-extractor-ClwwgABg.js +0 -2
  990. package/bundled-test-harness/assets/year-B6ctHikl.js +0 -2
  991. package/bundled-test-harness/assets/year-C11uAQE6.js +0 -78
  992. package/bundled-test-harness/assets/zip-file-def-B8XN-OS_.js +0 -288
  993. package/bundled-types/host-app/components/matrix/auth-button.gts +0 -39
  994. package/bundled-types/host-app/components/matrix/auth-container.gts +0 -69
  995. package/bundled-types/host-app/components/matrix/auth-form-field.gts +0 -43
@@ -0,0 +1,3460 @@
1
+ import { s as __toESM } from "./chunk-Rp0pCe6z.js";
2
+ import { n as decorateMethodV2, r as initializeDeferredDecorator, t as decorateFieldV2 } from "./runtime--fcdnjmJ-BoCBNIsz.js";
3
+ import { Ar as testRealmURL, Dr as testRRI, Po as isCardInstance, Ro as isFileDefInstance, Sc as Deferred, Wn as APP_BOXEL_REALM_EVENT_TYPE, uo as SupportedMimeType } from "./runtime-common-ClpqhbwG.js";
4
+ import { C as baseCardRef, K as realmURL, V as localId } from "./constants-CqKWhRfY.js";
5
+ import { wt as setComponentTemplate } from "./cache-DtDz7X5V-Wn8jRDfL.js";
6
+ import { r as service } from "./service-LFpJ8EEP.js";
7
+ import { H as templateFactory } from "./index-DaCZcoCY-CgzbilMy.js";
8
+ import "./component-BJO47HTh.js";
9
+ import { t as Component } from "./dist-CkA1rgqO.js";
10
+ import { n as tracked, t as cached } from "./tracking-800VJb8b.js";
11
+ import "./template-factory-ds9s0u8l.js";
12
+ import { n as getCardCollection } from "./card-collection-BXiO3i7R.js";
13
+ import { n as getCard } from "./card-resource-JGLjQUy6.js";
14
+ import { t as OperatorModeContainer } from "./container-Dj-5prh9.js";
15
+ import { M as waitUntil, T as settled, a as find, d as click, o as waitFor, r as typeIn } from "./dist-BOAdzfkP.js";
16
+ import { t as require_qunit } from "./qunit-C-Foo4Nd.js";
17
+ import { $ as withSavesHeldOpen, F as setupLocalIndexing, I as setupOnSave, L as setupRealmCacheTeardown, M as setupCardLogs, P as setupIntegrationTestRealm, Z as withCachedRealmSetup, _t as registerRealmServerRoute, et as withSlowSave, gt as registerDefaultRoutes, lt as setupRenderingTest, ot as setupOperatorModeStateCleanup, t as setupMockMatrix } from "./mock-matrix-DPQ0j2MD.js";
18
+ import { r as getService } from "./dist-CPfIHBla.js";
19
+ import { A as field, H as linksTo, U as linksToMany, a as CardDef, d as FileDef, s as Component$1, w as contains } from "./card-api-Dzje0smT.js";
20
+ import "./file-api-DPMJghBY.js";
21
+ import { t as BooleanField } from "./boolean-CcKPYUph.js";
22
+ import { t as string_default } from "./string-BHZZwNlZ.js";
23
+ import { n as renderComponent } from "./render-component-B15Z0e2v.js";
24
+ //#region tests/integration/store-test.gts
25
+ var import_qunit = /* @__PURE__ */ __toESM(require_qunit());
26
+ (0, import_qunit.module)("Integration | Store", function(hooks) {
27
+ setupRenderingTest(hooks);
28
+ setupOperatorModeStateCleanup(hooks);
29
+ let api;
30
+ let loader;
31
+ let loaderService;
32
+ let testRealm;
33
+ let testRealmAdapter;
34
+ let storeService;
35
+ let operatorModeStateService;
36
+ let cardStore;
37
+ let PersonDef;
38
+ let BoomPersonDef;
39
+ let EmployeeDef;
40
+ let ManagerDef;
41
+ let realmService;
42
+ setupLocalIndexing(hooks);
43
+ setupRealmCacheTeardown(hooks);
44
+ setupOnSave(hooks);
45
+ setupCardLogs(hooks, async () => await loader.import("@cardstack/base/card-api"));
46
+ let mockMatrixUtils = setupMockMatrix(hooks, {
47
+ loggedInAs: "@testuser:localhost",
48
+ activeRealms: [testRealmURL],
49
+ autostart: true
50
+ });
51
+ function forceGC() {
52
+ cardStore.sweep(api);
53
+ cardStore.sweep(api);
54
+ }
55
+ function setCardInOperatorModeState(cardURL, format = "isolated") {
56
+ operatorModeStateService.restore({ stacks: cardURL ? [[{
57
+ id: cardURL,
58
+ format
59
+ }]] : [[]] });
60
+ }
61
+ const noop = () => {};
62
+ async function writePerson(path, name) {
63
+ await testRealm.write(path, JSON.stringify({ data: {
64
+ attributes: { name },
65
+ meta: { adoptsFrom: {
66
+ module: testRRI("person"),
67
+ name: "Person"
68
+ } }
69
+ } }));
70
+ }
71
+ function interceptRealmEvents() {
72
+ let messageService = getService("message-service");
73
+ let deliver = messageService.relayRealmEvent.bind(messageService);
74
+ let captured = [];
75
+ messageService.relayRealmEvent = (event) => {
76
+ captured.push(event);
77
+ };
78
+ function find(url) {
79
+ return captured.find((event) => event.eventName === "index" && event.indexType === "incremental" && event.invalidations.includes(url));
80
+ }
81
+ return {
82
+ deliver,
83
+ async nextEventFor(url) {
84
+ await waitUntil(() => find(url) !== void 0, {
85
+ timeout: 1e4,
86
+ timeoutMessage: `the realm broadcast no incremental index event naming ${url}`
87
+ });
88
+ let event = find(url);
89
+ captured.length = 0;
90
+ return event;
91
+ },
92
+ restore() {
93
+ messageService.relayRealmEvent = deliver;
94
+ }
95
+ };
96
+ }
97
+ function countCardReads(pathFragment) {
98
+ let cardService = getService("card-service");
99
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
100
+ let count = 0;
101
+ cardService.fetchJSON = async (fetchUrl, args) => {
102
+ if (String(fetchUrl).includes(pathFragment) && (args?.method ?? "GET") === "GET") count++;
103
+ return originalFetchJSON(fetchUrl, args);
104
+ };
105
+ return {
106
+ get count() {
107
+ return count;
108
+ },
109
+ stop() {
110
+ delete cardService.fetchJSON;
111
+ }
112
+ };
113
+ }
114
+ async function settleCardRender(assert, id, selector, opts) {
115
+ let start = performance.now();
116
+ await settled();
117
+ let elapsedMs = Math.round(performance.now() - start);
118
+ if (!find(selector)) {
119
+ let held = storeService.peek(id, { type: opts?.type });
120
+ let error = storeService.peekError(id, { type: opts?.type });
121
+ console.error([
122
+ `[card-render-diag] ${selector} is not rendered after settled() (${elapsedMs}ms)`,
123
+ `reference count: ${storeService.getReferenceCount(id)}`,
124
+ `peek: ${held === void 0 ? "<nothing>" : isCardInstance(held) || isFileDefInstance(held) ? `instance ${held.id}` : `error ${JSON.stringify(held)}`}`,
125
+ `peekError: ${error ? JSON.stringify(error) : "<none>"}`
126
+ ].join("\n"));
127
+ } else if (elapsedMs > 1e3) console.warn(`[card-render-diag] ${selector} took ${elapsedMs}ms to load and render`);
128
+ assert.dom(selector).exists(`${id} is rendered`);
129
+ }
130
+ hooks.beforeEach(async function() {
131
+ class Person extends CardDef {
132
+ static {
133
+ decorateFieldV2(this.prototype, "name", [field], function() {
134
+ return contains(string_default);
135
+ });
136
+ }
137
+ #name = (initializeDeferredDecorator(this, "name"), void 0);
138
+ static {
139
+ decorateFieldV2(this.prototype, "hasError", [field], function() {
140
+ return contains(BooleanField);
141
+ });
142
+ }
143
+ #hasError = (initializeDeferredDecorator(this, "hasError"), void 0);
144
+ static {
145
+ decorateFieldV2(this.prototype, "bestFriend", [field], function() {
146
+ return linksTo(() => Person);
147
+ });
148
+ }
149
+ #bestFriend = (initializeDeferredDecorator(this, "bestFriend"), void 0);
150
+ static {
151
+ decorateFieldV2(this.prototype, "friends", [field], function() {
152
+ return linksToMany(() => Person);
153
+ });
154
+ }
155
+ #friends = (initializeDeferredDecorator(this, "friends"), void 0);
156
+ static {
157
+ decorateFieldV2(this.prototype, "boom", [field], function() {
158
+ return contains(string_default, { computeVia: function() {
159
+ if (this.hasError) throw new Error("intentional error thrown");
160
+ return "boom";
161
+ } });
162
+ });
163
+ }
164
+ #boom = (initializeDeferredDecorator(this, "boom"), void 0);
165
+ }
166
+ PersonDef = Person;
167
+ class BoomPerson extends CardDef {
168
+ static displayName = "Boom Person";
169
+ static {
170
+ decorateFieldV2(this.prototype, "name", [field], function() {
171
+ return contains(string_default);
172
+ });
173
+ }
174
+ #name = (initializeDeferredDecorator(this, "name"), void 0);
175
+ static isolated = class Isolated extends Component$1 {
176
+ static {
177
+ setComponentTemplate(templateFactory({
178
+ "id": "I6b4/CsV",
179
+ "block": "[[[1,\"Hello\\n\"],[8,[30,1,[\"name\"]],null,null,null],[1,\"!\\n\"],[1,[30,0,[\"boom\"]]]],[\"@fields\"],[]]",
180
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
181
+ "isStrictMode": true
182
+ }), this);
183
+ }
184
+ boom = () => intentionallyNotDefined();
185
+ };
186
+ }
187
+ BoomPersonDef = BoomPerson;
188
+ class Employee extends CardDef {
189
+ static displayName = "Employee";
190
+ static {
191
+ decorateFieldV2(this.prototype, "name", [field], function() {
192
+ return contains(string_default);
193
+ });
194
+ }
195
+ #name = (initializeDeferredDecorator(this, "name"), void 0);
196
+ static isolated = class Isolated extends Component$1 {
197
+ static {
198
+ setComponentTemplate(templateFactory({
199
+ "id": "TyvrA1L5",
200
+ "block": "[[[10,0],[14,\"data-test-employee-badge\",\"\"],[12],[1,\"Employee: \"],[8,[30,1,[\"name\"]],null,null,null],[13]],[\"@fields\"],[]]",
201
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
202
+ "isStrictMode": true
203
+ }), this);
204
+ }
205
+ };
206
+ }
207
+ EmployeeDef = Employee;
208
+ class Manager extends Employee {
209
+ static displayName = "Manager";
210
+ static isolated = class Isolated extends Component$1 {
211
+ static {
212
+ setComponentTemplate(templateFactory({
213
+ "id": "3Gw4m0Y6",
214
+ "block": "[[[10,0],[14,\"data-test-manager-badge\",\"\"],[12],[1,\"Manager: \"],[8,[30,1,[\"name\"]],null,null,null],[13]],[\"@fields\"],[]]",
215
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
216
+ "isStrictMode": true
217
+ }), this);
218
+ }
219
+ };
220
+ }
221
+ ManagerDef = Manager;
222
+ loaderService = getService("loader-service");
223
+ loader = loaderService.loader;
224
+ api = await loader.import("@cardstack/base/card-api");
225
+ storeService = getService("store");
226
+ operatorModeStateService = getService("operator-mode-state-service");
227
+ cardStore = storeService.store;
228
+ realmService = getService("realm");
229
+ await withCachedRealmSetup(async () => {
230
+ ({adapter: testRealmAdapter, realm: testRealm} = await setupIntegrationTestRealm({
231
+ mockMatrixUtils,
232
+ contents: {
233
+ "person.gts": { Person },
234
+ "boom-person.gts": { BoomPerson },
235
+ "employee.gts": { Employee },
236
+ "manager.gts": { Manager },
237
+ "Person/hassan.json": new Person({ name: "Hassan" }),
238
+ "Person/jade.json": new Person({ name: "Jade" }),
239
+ "Person/queenzy.json": new Person({ name: "Queenzy" }),
240
+ "Person/germaine.json": new Person({ name: "Germaine" }),
241
+ "Person/boris.json": new Person({ name: "Boris" })
242
+ }
243
+ }));
244
+ });
245
+ await realmService.login(testRealmURL);
246
+ });
247
+ hooks.afterEach(function() {
248
+ getService("network").virtualNetwork.removeRealmMapping("@test-prefix/");
249
+ });
250
+ (0, import_qunit.test)("can peek a card instance", async function(assert) {
251
+ storeService.addReference(`${testRealmURL}Person/hassan`);
252
+ await storeService.flush();
253
+ let instance = storeService.peek(`${testRealmURL}Person/hassan`);
254
+ assert.true(isCardInstance(instance), "peeked item is a card instance");
255
+ });
256
+ (0, import_qunit.test)("can peek a card by local id", async function(assert) {
257
+ storeService.addReference(`${testRealmURL}Person/hassan`);
258
+ await storeService.flush();
259
+ let instanceA = storeService.peek(`${testRealmURL}Person/hassan`);
260
+ let instanceB = storeService.peek(instanceA[localId]);
261
+ assert.true(isCardInstance(instanceB), "peeked item is a card instance");
262
+ assert.strictEqual(instanceA, instanceB, "the same instance is returned by both remote ID and local ID");
263
+ });
264
+ (0, import_qunit.test)("can peek a card error when no stale instance exists", async function(assert) {
265
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
266
+ attributes: {
267
+ name: "Hassan",
268
+ hasError: true
269
+ },
270
+ meta: { adoptsFrom: {
271
+ module: testRRI("person"),
272
+ name: "Person"
273
+ } }
274
+ } }));
275
+ storeService.addReference(`${testRealmURL}Person/hassan`);
276
+ await storeService.flush();
277
+ let error = storeService.peek(`${testRealmURL}Person/hassan`);
278
+ assert.false(isCardInstance(error), "error is not a card instance");
279
+ assert.ok(error.message.includes("intentional error thrown"), "error message is correct");
280
+ });
281
+ (0, import_qunit.test)("peek returns a stale instance when the server state reflects an error", async function(assert) {
282
+ storeService.addReference(`${testRealmURL}Person/hassan`);
283
+ await storeService.flush();
284
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
285
+ attributes: {
286
+ name: "Hassan",
287
+ hasError: true
288
+ },
289
+ meta: { adoptsFrom: {
290
+ module: testRRI("person"),
291
+ name: "Person"
292
+ } }
293
+ } }));
294
+ await waitUntil(() => storeService.peekError(`${testRealmURL}Person/hassan`));
295
+ let staleInstance = storeService.peek(`${testRealmURL}Person/hassan`);
296
+ assert.true(isCardInstance(staleInstance), "the peek-ed instance is not an error");
297
+ });
298
+ (0, import_qunit.test)("peek for an uncached returns undefined", async function(assert) {
299
+ let instance = storeService.peek(`${testRealmURL}Person/does-not-exist`);
300
+ assert.strictEqual(instance, void 0, "instance is undefined");
301
+ });
302
+ (0, import_qunit.test)("can use registered prefix ids across store APIs", async function(assert) {
303
+ getService("network").virtualNetwork.addRealmMapping("@test-prefix/", testRealmURL);
304
+ storeService.addReference("@test-prefix/Person/hassan");
305
+ await storeService.flush();
306
+ let byPrefix = storeService.peek("@test-prefix/Person/hassan");
307
+ let byUrl = storeService.peek(`${testRealmURL}Person/hassan`);
308
+ assert.true(isCardInstance(byPrefix), "prefix id resolves to a card");
309
+ assert.strictEqual(byPrefix, byUrl, "prefix id and resolved URL return the same instance");
310
+ assert.strictEqual(storeService.getReferenceCount("@test-prefix/Person/hassan"), 1, "prefix id and resolved URL share a single reference count");
311
+ assert.strictEqual(storeService.getReferenceCount(`${testRealmURL}Person/hassan`), 1, "resolved URL sees the same reference count");
312
+ storeService.dropReference("@test-prefix/Person/hassan");
313
+ assert.strictEqual(storeService.getReferenceCount(`${testRealmURL}Person/hassan`), 0, "dropping a prefix reference clears the resolved URL reference count");
314
+ let saveFinished = new Deferred();
315
+ this.onSave((url) => {
316
+ if (url.href === `${testRealmURL}Person/hassan`) {
317
+ assert.strictEqual(url.href, `${testRealmURL}Person/hassan`);
318
+ assert.strictEqual(storeService.getReferenceCount(`${testRealmURL}Person/hassan`), 0, "save() does not create a separate resolved-url reference count");
319
+ assert.strictEqual(storeService.getReferenceCount("@test-prefix/Person/hassan"), 0, "save() does not create a separate prefix reference count");
320
+ saveFinished.fulfill();
321
+ }
322
+ });
323
+ storeService.save("@test-prefix/Person/hassan");
324
+ await saveFinished;
325
+ storeService.addReference("@test-prefix/Person/boris");
326
+ await storeService.flush();
327
+ await storeService.delete("@test-prefix/Person/boris");
328
+ assert.strictEqual(storeService.peek("@test-prefix/Person/boris"), void 0, "delete() clears the prefix-form card identity from the store");
329
+ assert.strictEqual(storeService.peek(`${testRealmURL}Person/boris`), void 0, "delete() clears the resolved card identity from the store");
330
+ let file = await testRealmAdapter.openFile(`Person/boris.json`);
331
+ assert.strictEqual(file, void 0, "delete() removes the remote card");
332
+ });
333
+ (0, import_qunit.test)("deleting a linked target rewrites a loaded consumer linksTo slot to a broken-link sentinel", async function(assert) {
334
+ storeService.addReference(`${testRealmURL}Person/hassan`);
335
+ storeService.addReference(`${testRealmURL}Person/boris`);
336
+ await storeService.flush();
337
+ let hassan = storeService.peek(`${testRealmURL}Person/hassan`);
338
+ hassan.bestFriend = storeService.peek(`${testRealmURL}Person/boris`);
339
+ await settled();
340
+ assert.strictEqual(api.getRelationshipMembershipState(hassan, "bestFriend").membership[0].kind, "present", "the consumer link resolves to the target before the delete");
341
+ await storeService.delete(`${testRealmURL}Person/boris`);
342
+ let after = api.getRelationshipMembershipState(hassan, "bestFriend").membership[0];
343
+ assert.strictEqual(after.kind, "not-found", "deleting the target rewrites the consumer slot to a broken-link sentinel without a reload");
344
+ assert.strictEqual(after.reference, `${testRealmURL}Person/boris`, "the sentinel preserves the deleted target reference for the placeholder");
345
+ });
346
+ (0, import_qunit.test)("deleting a linked target rewrites only the matching element of a loaded consumer linksToMany slot", async function(assert) {
347
+ storeService.addReference(`${testRealmURL}Person/hassan`);
348
+ storeService.addReference(`${testRealmURL}Person/boris`);
349
+ storeService.addReference(`${testRealmURL}Person/jade`);
350
+ await storeService.flush();
351
+ let hassan = storeService.peek(`${testRealmURL}Person/hassan`);
352
+ let boris = storeService.peek(`${testRealmURL}Person/boris`);
353
+ hassan.friends = [storeService.peek(`${testRealmURL}Person/jade`), boris];
354
+ await settled();
355
+ let before = api.getRelationshipMembershipState(hassan, "friends").membership;
356
+ assert.deepEqual(before.map((s) => s.kind), ["present", "present"], "both linksToMany elements resolve before the delete");
357
+ await storeService.delete(`${testRealmURL}Person/boris`);
358
+ let after = api.getRelationshipMembershipState(hassan, "friends").membership;
359
+ let borisEntry = after.find((s) => s.reference === `${testRealmURL}Person/boris`);
360
+ let jadeEntry = after.find((s) => s.reference === `${testRealmURL}Person/jade`);
361
+ assert.strictEqual(borisEntry?.kind, "not-found", "the deleted element becomes a broken-link sentinel");
362
+ assert.strictEqual(jadeEntry?.kind, "present", "the surviving element is left untouched");
363
+ });
364
+ (0, import_qunit.test)("peekError returns the server state error when a stale instance exists", async function(assert) {
365
+ storeService.addReference(`${testRealmURL}Person/hassan`);
366
+ await storeService.flush();
367
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
368
+ attributes: {
369
+ name: "Hassan",
370
+ hasError: true
371
+ },
372
+ meta: { adoptsFrom: {
373
+ module: testRRI("person"),
374
+ name: "Person"
375
+ } }
376
+ } }));
377
+ await waitUntil(() => storeService.peekError(`${testRealmURL}Person/hassan`));
378
+ let error = storeService.peekError(`${testRealmURL}Person/hassan`);
379
+ assert.false(isCardInstance(error), "error is not a card instance");
380
+ assert.ok(error.message.includes("intentional error thrown"), "error message is correct");
381
+ });
382
+ (0, import_qunit.test)("can add reference to a card url", async function(assert) {
383
+ let instance = storeService.peek(`${testRealmURL}hassan`);
384
+ assert.strictEqual(instance, void 0, "instance is not in store yet");
385
+ storeService.addReference(`${testRealmURL}Person/hassan`);
386
+ await storeService.flush();
387
+ instance = storeService.peek(`${testRealmURL}Person/hassan`);
388
+ if (isCardInstance(instance)) assert.strictEqual(instance.name, "Hassan", "instance is cached in store");
389
+ else assert.ok(false, `expected instance to be a card:${JSON.stringify(instance, null, 2)}`);
390
+ forceGC();
391
+ instance = storeService.peek(`${testRealmURL}Person/hassan`);
392
+ if (isCardInstance(instance)) assert.strictEqual(instance.name, "Hassan", "instance is cached in store after GC");
393
+ else assert.ok(false, `expected instance to be a card:${JSON.stringify(instance, null, 2)} after GC`);
394
+ });
395
+ (0, import_qunit.test)("can add reference to a local id", async function(assert) {
396
+ let instance = new PersonDef({ name: "Andrea" });
397
+ await storeService.addWithoutPersisting(instance);
398
+ storeService.addReference(instance[localId]);
399
+ forceGC();
400
+ let peekedInstance = storeService.peek(instance[localId]);
401
+ assert.strictEqual(peekedInstance, instance, "instance is not garbage collected");
402
+ });
403
+ (0, import_qunit.test)("a render-context load does not set up the autosave change subscription", async function(assert) {
404
+ let cardService = getService("card-service");
405
+ let originalGetAPI = cardService.getAPI.bind(cardService);
406
+ let realApi = await originalGetAPI();
407
+ let trueSubscribe = realApi.subscribeToChanges;
408
+ let subscribeCount = 0;
409
+ cardService.getAPI = async () => new Proxy(realApi, { get(target, prop, receiver) {
410
+ if (prop === "subscribeToChanges") return (...args) => {
411
+ subscribeCount++;
412
+ return trueSubscribe(...args);
413
+ };
414
+ return Reflect.get(target, prop, receiver);
415
+ } });
416
+ try {
417
+ await storeService.addWithoutPersisting(new PersonDef({ name: "Mango" }));
418
+ assert.true(subscribeCount > 0, "the live store subscribes a loaded instance for autosave");
419
+ subscribeCount = 0;
420
+ globalThis.__boxelRenderContext = true;
421
+ await getService("render-store").addWithoutPersisting(new PersonDef({ name: "Van Gogh" }));
422
+ assert.strictEqual(subscribeCount, 0, "the render store does not subscribe a loaded instance for autosave");
423
+ } finally {
424
+ cardService.getAPI = originalGetAPI;
425
+ delete globalThis.__boxelRenderContext;
426
+ }
427
+ });
428
+ (0, import_qunit.test)("a card render absorbs a blocked write, a headless command reports it", async function(assert) {
429
+ globalThis.__boxelPrerenderApp = true;
430
+ try {
431
+ let rendered = new PersonDef({ name: "Andrea" });
432
+ assert.strictEqual(await storeService.add(rendered), rendered, "a render keeps the instance rather than failing");
433
+ globalThis.__boxelHeadlessCommand = true;
434
+ await assert.rejects(storeService.add(new PersonDef({ name: "Van Gogh" })), /persistence block still raised/, "a command reports the blocked write");
435
+ let ephemeral = new PersonDef({ name: "Mango" });
436
+ assert.strictEqual(await storeService.addWithoutPersisting(ephemeral), ephemeral, "a memory-only add is served as asked");
437
+ } finally {
438
+ delete globalThis.__boxelHeadlessCommand;
439
+ delete globalThis.__boxelPrerenderApp;
440
+ }
441
+ });
442
+ (0, import_qunit.test)("restoring sessions from storage skips the re-walk when the session blob is unchanged", function(assert) {
443
+ let walks = 0;
444
+ let originalGetOrCreate = realmService.getOrCreateRealmResource.bind(realmService);
445
+ realmService.getOrCreateRealmResource = (...args) => {
446
+ walks++;
447
+ return originalGetOrCreate(...args);
448
+ };
449
+ try {
450
+ realmService.lastRestoredSessionsString = void 0;
451
+ let before = walks;
452
+ realmService.restoreSessionsFromStorage();
453
+ assert.true(walks - before > 0, "the first restore walks the stored sessions");
454
+ before = walks;
455
+ realmService.restoreSessionsFromStorage();
456
+ assert.strictEqual(walks - before, 0, "a restore with an unchanged blob does not re-walk");
457
+ realmService.lastRestoredSessionsString = "stale-sentinel";
458
+ before = walks;
459
+ realmService.restoreSessionsFromStorage();
460
+ assert.true(walks - before > 0, "a restore re-walks once the stored blob no longer matches the memo");
461
+ } finally {
462
+ realmService.getOrCreateRealmResource = originalGetOrCreate;
463
+ }
464
+ });
465
+ (0, import_qunit.test)("getFields is memoized per instance in the render context and invalidates as the instance grows", function(assert) {
466
+ let person = new PersonDef({ name: "Mango" });
467
+ try {
468
+ globalThis.__boxelRenderContext = true;
469
+ let first = api.getFields(person, { usedLinksToFieldsOnly: true });
470
+ let second = api.getFields(person, { usedLinksToFieldsOnly: true });
471
+ assert.strictEqual(first, second, "a repeat call in the render context returns the memoized field map");
472
+ assert.notOk("bestFriend" in first, "an unused linksTo field is absent before it is populated");
473
+ person.bestFriend = new PersonDef({ name: "Van Gogh" });
474
+ let third = api.getFields(person, { usedLinksToFieldsOnly: true });
475
+ assert.notStrictEqual(third, first, "growing the instance invalidates the memo");
476
+ assert.ok("bestFriend" in third, "the now-used linksTo field appears after the bucket grows");
477
+ delete globalThis.__boxelRenderContext;
478
+ let live1 = api.getFields(person, { usedLinksToFieldsOnly: true });
479
+ let live2 = api.getFields(person, { usedLinksToFieldsOnly: true });
480
+ assert.notStrictEqual(live1, live2, "the live app always gets a fresh field map");
481
+ } finally {
482
+ delete globalThis.__boxelRenderContext;
483
+ }
484
+ });
485
+ (0, import_qunit.test)("can drop reference to a card url", async function(assert) {
486
+ storeService.addReference(`${testRealmURL}Person/hassan`);
487
+ await storeService.flush();
488
+ let instance = storeService.peek(`${testRealmURL}Person/hassan`);
489
+ assert.ok(instance, "instance is in store");
490
+ storeService.dropReference(`${testRealmURL}Person/hassan`);
491
+ forceGC();
492
+ assert.strictEqual(storeService.peek(`${testRealmURL}Person/hassan`), void 0, "instance has been garbage collected from the store");
493
+ });
494
+ (0, import_qunit.test)("can drop reference to a local id", async function(assert) {
495
+ let instance = new PersonDef({ name: "Andrea" });
496
+ await storeService.addWithoutPersisting(instance);
497
+ storeService.addReference(instance[localId]);
498
+ storeService.dropReference(instance[localId]);
499
+ forceGC();
500
+ let peekedInstance = storeService.peek(instance[localId]);
501
+ assert.strictEqual(peekedInstance, void 0, "instance is garbage collected");
502
+ });
503
+ (0, import_qunit.test)("file-meta instance is retained when referenced", async function(assert) {
504
+ await testRealm.write("hero.png", "mock hero image");
505
+ let fileUrl = `${testRealmURL}hero.png`;
506
+ let fileInstance = await storeService.get(fileUrl, { type: "file-meta" });
507
+ assert.ok(fileInstance, "file meta instance is loaded");
508
+ assert.ok(fileInstance.constructor?.isFileDef, "file meta instance is a FileDef");
509
+ storeService.addReference(fileUrl);
510
+ forceGC();
511
+ let peekedInstance = cardStore.getFileMeta(fileUrl);
512
+ assert.strictEqual(peekedInstance, fileInstance, "file meta instance is retained after GC with reference");
513
+ });
514
+ (0, import_qunit.test)("file-meta instance is garbage collected when references drop", async function(assert) {
515
+ await testRealm.write("hero.png", "mock hero image");
516
+ let fileUrl = `${testRealmURL}hero.png`;
517
+ await storeService.get(fileUrl, { type: "file-meta" });
518
+ storeService.addReference(fileUrl);
519
+ storeService.dropReference(fileUrl);
520
+ forceGC();
521
+ assert.strictEqual(cardStore.getFileMeta(fileUrl), void 0, "file meta instance is garbage collected after reference drop");
522
+ });
523
+ (0, import_qunit.test)("realm subscription is removed when file-meta reference count drops to zero", async function(assert) {
524
+ await testRealm.write("hero.png", "mock hero image");
525
+ let fileUrl = `${testRealmURL}hero.png`;
526
+ let subscriptions = storeService.subscriptions;
527
+ assert.false(subscriptions.has(testRealmURL), "realm is not subscribed before adding file-meta reference");
528
+ storeService.addReference(fileUrl, { type: "file-meta" });
529
+ assert.true(subscriptions.has(testRealmURL), "realm subscription is created for file-meta reference");
530
+ storeService.dropReference(fileUrl);
531
+ assert.false(subscriptions.has(testRealmURL), "realm subscription is removed when file-meta reference reaches zero");
532
+ });
533
+ (0, import_qunit.test)("add stores FileDef dependencies", async function(assert) {
534
+ class FileCard extends CardDef {
535
+ static {
536
+ decorateFieldV2(this.prototype, "attachment", [field], function() {
537
+ return linksTo(FileDef);
538
+ });
539
+ }
540
+ #attachment = (initializeDeferredDecorator(this, "attachment"), void 0);
541
+ }
542
+ let fileUrl = `${testRealmURL}hero.png`;
543
+ let fileDef = new FileDef({
544
+ id: fileUrl,
545
+ sourceUrl: fileUrl,
546
+ url: fileUrl,
547
+ name: "hero.png",
548
+ contentType: "image/png"
549
+ });
550
+ let card = new FileCard({ attachment: fileDef });
551
+ await storeService.addWithoutPersisting(card);
552
+ assert.strictEqual(storeService.peek(fileUrl, { type: "file-meta" }), fileDef, "file meta dependency is cached in file-meta store");
553
+ });
554
+ (0, import_qunit.test)("card read of a binary file URL is rerouted to file-meta", async function(assert) {
555
+ await testRealm.write("hero.png", "mock hero image");
556
+ let fileUrl = `${testRealmURL}hero.png`;
557
+ let result = await storeService.get(fileUrl);
558
+ assert.ok(result.constructor?.isFileDef, "card read returns a FileDef via the safety-net reroute");
559
+ let fileInstance = await storeService.get(fileUrl, { type: "file-meta" });
560
+ assert.ok(fileInstance.constructor?.isFileDef, "file-meta read returns a FileDef");
561
+ assert.strictEqual(storeService.peekError(fileUrl), void 0, "no error cached on the card bucket");
562
+ assert.strictEqual(storeService.peekError(fileUrl, { type: "file-meta" }), void 0, "no error cached on the file-meta bucket");
563
+ });
564
+ (0, import_qunit.test)("a file the realm does not hold is reported as a missing file", async function(assert) {
565
+ let missingFileUrl = `${testRealmURL}missing.png`;
566
+ let error = await storeService.get(missingFileUrl, { type: "file-meta" });
567
+ assert.strictEqual(error.status, 404, "the error carries the HTTP status");
568
+ assert.strictEqual(error.title, "File Not Found", "a missing file is titled as a missing file, not a missing card");
569
+ assert.strictEqual(error.message, `The file ${missingFileUrl} does not exist`, "the message names a file, not a card");
570
+ });
571
+ (0, import_qunit.test)("garbage collects cards that only consume each other", async function(assert) {
572
+ let alpha = new PersonDef({ name: "Alpha" });
573
+ let beta = new PersonDef({ name: "Beta" });
574
+ alpha.bestFriend = beta;
575
+ beta.bestFriend = alpha;
576
+ await storeService.addWithoutPersisting(alpha);
577
+ await storeService.addWithoutPersisting(beta);
578
+ assert.strictEqual(storeService.peek(alpha[localId]), alpha, "alpha is present before GC");
579
+ assert.strictEqual(storeService.peek(beta[localId]), beta, "beta is present before GC");
580
+ forceGC();
581
+ assert.strictEqual(storeService.peek(alpha[localId]), void 0, "alpha is garbage collected");
582
+ assert.strictEqual(storeService.peek(beta[localId]), void 0, "beta is garbage collected");
583
+ });
584
+ (0, import_qunit.test)("can manually save an instance", async function(assert) {
585
+ assert.expect(2);
586
+ storeService.addReference(`${testRealmURL}Person/hassan`);
587
+ await storeService.flush();
588
+ this.onSave((url, doc) => {
589
+ assert.strictEqual(url.href, `${testRealmURL}Person/hassan`, "the saved card id is correct");
590
+ assert.strictEqual(doc.data.attributes?.name, "Hassan", "save data is correct");
591
+ });
592
+ storeService.save(`${testRealmURL}Person/hassan`);
593
+ });
594
+ (0, import_qunit.test)("can create an instance", async function(assert) {
595
+ let url = await storeService.create({ data: {
596
+ attributes: { name: "Andrea" },
597
+ meta: { adoptsFrom: {
598
+ module: testRRI("person"),
599
+ name: "Person"
600
+ } }
601
+ } });
602
+ assert.strictEqual(typeof url, "string", "received a url for new instance");
603
+ let instance = storeService.peek(url);
604
+ assert.strictEqual(instance.id, url);
605
+ assert.strictEqual(instance.name, "Andrea");
606
+ let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
607
+ assert.ok(file, "file exists");
608
+ let fileJSON = JSON.parse(file.content);
609
+ assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
610
+ });
611
+ (0, import_qunit.test)("can handle card error when creating an instance", async function(assert) {
612
+ let error = await storeService.create({ data: {
613
+ attributes: {
614
+ name: "Andrea",
615
+ hasError: true
616
+ },
617
+ meta: { adoptsFrom: {
618
+ module: testRRI("person"),
619
+ name: "Person"
620
+ } }
621
+ } });
622
+ assert.strictEqual(typeof error, "object", "received a error for new instance");
623
+ assert.ok(error.message.includes("intentional error thrown", "the error message is correct"));
624
+ });
625
+ (0, import_qunit.test)("can handle a rendering card error when creating an instance", async function(assert) {
626
+ let instance = new BoomPersonDef({ name: "Andrea" });
627
+ let error = await storeService.add(instance, { realm: testRealmURL });
628
+ storeService.addReference(instance[localId]);
629
+ await storeService.flush();
630
+ let stale = storeService.peek(instance[localId]);
631
+ if (isCardInstance(stale)) assert.strictEqual(stale.name, "Andrea", "the stale card state is correct");
632
+ else assert.ok(false, `expected an instance but got a card error: "${stale.message}"`);
633
+ let peekedError = storeService.peekError(instance[localId]);
634
+ assert.strictEqual(peekedError, error, "the output of store.add is the peek-ed error");
635
+ if (!isCardInstance(error)) {
636
+ assert.strictEqual(error.id, instance[localId], "the error doc id is the local id of the instance");
637
+ assert.ok(error.message.includes("intentionallyNotDefined is not defined"));
638
+ loaderService.resetLoader();
639
+ await testRealm.write(`boom-person.gts`, `
640
+ import { contains, field, CardDef, Component, StringField } from '@cardstack/base/card-api';
641
+
642
+ export class BoomPerson extends CardDef {
643
+ static displayName = 'Boom Person';
644
+ @field name = contains(StringField);
645
+ static isolated = class Isolated extends Component<typeof this> {
646
+ <template>
647
+ Hello
648
+ <@fields.firstName />!
649
+ </template>
650
+ };
651
+ }
652
+ `.trim());
653
+ await waitUntil(() => !storeService.peekError(instance[localId]), { timeout: 5e3 });
654
+ await waitUntil(() => {
655
+ let card = storeService.peek(instance[localId]);
656
+ return Boolean(card && isCardInstance(card));
657
+ }, { timeout: 5e3 });
658
+ let peek = storeService.peek(instance[localId]);
659
+ assert.strictEqual(peek.name, "Andrea", "peek-ed value has been updated to be the fixed card instance");
660
+ } else assert.ok(false, "expected a card error but got a running instance");
661
+ });
662
+ (0, import_qunit.test)("can add a running instance to the store", async function(assert) {
663
+ assert.expect(5);
664
+ this.onSave((_, doc) => {
665
+ assert.strictEqual(doc.data.attributes?.name, "Andrea", "card data is correct");
666
+ });
667
+ let instance = new PersonDef({ name: "Andrea" });
668
+ await storeService.add(instance);
669
+ assert.ok(instance.id, "instance has been assigned remote id");
670
+ let peekedInstance = storeService.peek(instance.id);
671
+ assert.strictEqual(instance, peekedInstance, "instance is the same");
672
+ let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
673
+ assert.ok(file, "file exists");
674
+ let fileJSON = JSON.parse(file.content);
675
+ assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
676
+ });
677
+ (0, import_qunit.test)("add() does not persist an existing card when the realm is read-only", async function(assert) {
678
+ storeService.realm.permissions = () => ({
679
+ get canRead() {
680
+ return true;
681
+ },
682
+ get canWrite() {
683
+ return false;
684
+ }
685
+ });
686
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
687
+ let writes = [];
688
+ this.onSave((url) => writes.push(url.href));
689
+ instance.name = "Hassan Updated";
690
+ let result = await storeService.add(instance);
691
+ await settled();
692
+ assert.deepEqual(writes, [], "no write is attempted without permission");
693
+ assert.true(isCardInstance(result), "add() still resolves with the instance rather than a permission error");
694
+ let file = await testRealmAdapter.openFile("Person/hassan.json");
695
+ assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Hassan", "the durable document is untouched");
696
+ });
697
+ (0, import_qunit.test)("add() reports its save in the card save state", async function(assert) {
698
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
699
+ instance.name = "Hassan Updated";
700
+ await storeService.add(instance);
701
+ let saveState = storeService.getSaveState(instance.id);
702
+ assert.false(saveState.hasUnsavedChanges, "the card no longer reports unsaved changes");
703
+ assert.ok(saveState.lastSaved, "lastSaved reflects the add()-driven save");
704
+ assert.strictEqual(saveState.lastSaveError, void 0, "no save error is reported");
705
+ assert.false(saveState.isSaving, "the save is no longer in flight");
706
+ });
707
+ (0, import_qunit.test)("add() records a persistence failure in the card save state", async function(assert) {
708
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
709
+ instance.name = "Hassan Updated";
710
+ let store = storeService;
711
+ store.saveCardDocument = async () => {
712
+ throw new Error("intentional persistence failure");
713
+ };
714
+ try {
715
+ await storeService.add(instance);
716
+ } finally {
717
+ delete store.saveCardDocument;
718
+ }
719
+ let saveState = storeService.getSaveState(instance.id);
720
+ assert.ok(saveState.lastSaveError, "the failure is visible to the save indicator, not only to the caller");
721
+ assert.false(saveState.isSaving, "the save is no longer in flight");
722
+ });
723
+ (0, import_qunit.test)("add() awaits durable persistence for an existing card", async function(assert) {
724
+ let queenzy = await storeService.get(`${testRealmURL}Person/queenzy`);
725
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
726
+ instance.name = "Hassan Updated";
727
+ instance.bestFriend = queenzy;
728
+ let result = await storeService.add(instance);
729
+ assert.true(isCardInstance(result), "add() resolves with the card instance");
730
+ let file = await testRealmAdapter.openFile("Person/hassan.json");
731
+ let fileJSON = JSON.parse(file.content);
732
+ assert.strictEqual(fileJSON.data.attributes.name, "Hassan Updated", "the scalar mutation is durable as soon as add() resolves");
733
+ assert.ok(fileJSON.data.relationships.bestFriend.links.self.endsWith("queenzy"), "the link mutation is durable as soon as add() resolves");
734
+ });
735
+ (0, import_qunit.test)("add() stays pending until an existing card is durably persisted", async function(assert) {
736
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
737
+ instance.name = "Hassan Updated";
738
+ let store = storeService;
739
+ let gate = new Deferred();
740
+ let originalPersist = store.persistAndUpdate;
741
+ store.persistAndUpdate = async (...args) => {
742
+ await gate.promise;
743
+ return await originalPersist.call(store, ...args);
744
+ };
745
+ try {
746
+ let resolved = false;
747
+ let addPromise = storeService.add(instance).then((r) => {
748
+ resolved = true;
749
+ return r;
750
+ });
751
+ for (let i = 0; i < 10; i++) await Promise.resolve();
752
+ assert.false(resolved, "add() has not resolved while persistence is gated");
753
+ gate.fulfill();
754
+ await addPromise;
755
+ assert.true(resolved, "add() resolves once persistence completes");
756
+ } finally {
757
+ delete store.persistAndUpdate;
758
+ }
759
+ let file = await testRealmAdapter.openFile("Person/hassan.json");
760
+ assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Hassan Updated", "the mutation is durably persisted");
761
+ });
762
+ (0, import_qunit.test)("add() surfaces persistence failures for an existing card", async function(assert) {
763
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
764
+ instance.name = "Hassan Updated";
765
+ let store = storeService;
766
+ store.saveCardDocument = async () => {
767
+ throw new Error("intentional persistence failure");
768
+ };
769
+ let result;
770
+ try {
771
+ result = await storeService.add(instance);
772
+ } finally {
773
+ delete store.saveCardDocument;
774
+ }
775
+ assert.false(isCardInstance(result), "add() resolves with a card error rather than the instance when persistence fails");
776
+ assert.ok(result.message.includes("intentional persistence failure"), "the persistence error propagates to the caller instead of being swallowed");
777
+ });
778
+ (0, import_qunit.test)("can add a serialized instance to the store", async function(assert) {
779
+ assert.expect(6);
780
+ this.onSave((_, doc) => {
781
+ assert.strictEqual(doc.data.attributes?.name, "Andrea", "card data is correct");
782
+ });
783
+ let instance = await storeService.add({ data: {
784
+ attributes: { name: "Andrea" },
785
+ meta: { adoptsFrom: {
786
+ module: testRRI("person"),
787
+ name: "Person"
788
+ } }
789
+ } });
790
+ assert.ok(instance.id, "instance has been assigned remote id");
791
+ let peekedInstance = storeService.peek(instance.id);
792
+ assert.strictEqual(instance, peekedInstance, "instance is the same");
793
+ assert.strictEqual(instance.name, "Andrea", "instance data is correct");
794
+ let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
795
+ assert.ok(file, "file exists");
796
+ let fileJSON = JSON.parse(file.content);
797
+ assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
798
+ });
799
+ (0, import_qunit.test)("can skip saving when adding to the store", async function(assert) {
800
+ assert.expect(3);
801
+ this.onSave(() => {
802
+ assert.ok(false, "save should not happen");
803
+ });
804
+ let instance = await storeService.addWithoutPersisting({ data: {
805
+ attributes: { name: "Andrea" },
806
+ meta: { adoptsFrom: {
807
+ module: testRRI("person"),
808
+ name: "Person"
809
+ } }
810
+ } }, {});
811
+ assert.strictEqual(instance.id, void 0, "instance has NOT been assigned remote id");
812
+ let peekedInstance = storeService.peek(instance[localId]);
813
+ assert.strictEqual(instance, peekedInstance, "instance is the same");
814
+ assert.strictEqual(instance.name, "Andrea", "instance data is correct");
815
+ });
816
+ (0, import_qunit.test)("can skip waiting for the save when adding to the store", async function(assert) {
817
+ assert.expect(6);
818
+ let didSave = false;
819
+ this.onSave((_, doc) => {
820
+ didSave = true;
821
+ assert.strictEqual(doc.data.attributes?.name, "Andrea", "card data is correct");
822
+ });
823
+ let instance = new PersonDef({ name: "Andrea" });
824
+ await storeService.addWithoutWaiting(instance);
825
+ assert.false(didSave, "the instance has not saved yet");
826
+ await waitUntil(() => didSave, { timeout: 1e4 });
827
+ assert.ok(instance.id, "instance has been assigned remote id");
828
+ let peekedInstance = storeService.peek(instance.id);
829
+ assert.strictEqual(instance, peekedInstance, "instance is the same");
830
+ let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
831
+ assert.ok(file, "file exists");
832
+ let fileJSON = JSON.parse(file.content);
833
+ assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
834
+ });
835
+ (0, import_qunit.test)("can set realmURL when adding to the store", async function(assert) {
836
+ let instance = new PersonDef({ name: "Andrea" });
837
+ assert.strictEqual(instance[realmURL]?.href, void 0, "realmURL meta is not set on the instance");
838
+ await storeService.addWithoutPersisting(instance, { realm: testRealmURL });
839
+ assert.strictEqual(instance[realmURL]?.href, testRealmURL, "realmURL meta was set on the instance");
840
+ });
841
+ (0, import_qunit.test)("can add linked cards to the store when adding a card", async function(assert) {
842
+ let wu = new PersonDef({ name: "Wu" });
843
+ let michael = new PersonDef({ name: "Michael" });
844
+ let lin = new PersonDef({
845
+ name: "Lin",
846
+ bestFriend: wu,
847
+ friends: [michael]
848
+ });
849
+ await storeService.addWithoutPersisting(lin);
850
+ let peekedMichael = storeService.peek(michael[localId]);
851
+ assert.strictEqual(peekedMichael, michael, "michael instance added to store");
852
+ let peekedWu = storeService.peek(wu[localId]);
853
+ assert.strictEqual(peekedWu, wu, "wu instance added to store");
854
+ });
855
+ (0, import_qunit.test)("can reject a card added to the store that has a conflicting local ID for a given URL", async function(assert) {
856
+ storeService.addReference(`${testRealmURL}Person/hassan`);
857
+ await storeService.flush();
858
+ let doc = { data: {
859
+ type: "card",
860
+ id: testRRI("Person/hassan"),
861
+ attributes: { name: "Hassan" },
862
+ meta: { adoptsFrom: {
863
+ module: testRRI("person"),
864
+ name: "Person"
865
+ } }
866
+ } };
867
+ let conflictingInstance = await api.createFromSerialized(doc.data, doc, void 0);
868
+ try {
869
+ await storeService.addWithoutPersisting(conflictingInstance);
870
+ throw new Error("expected exception to be thrown");
871
+ } catch (err) {
872
+ assert.ok(err.message.includes("has conflicting instance id in store"), "the expected error was thrown");
873
+ }
874
+ });
875
+ (0, import_qunit.test)("added instance that was previously not saved will begin to auto save after being added", async function(assert) {
876
+ assert.expect(2);
877
+ let instance = new PersonDef({ name: "Andrea" });
878
+ await storeService.add(instance);
879
+ this.onSave((url, doc) => {
880
+ assert.strictEqual(url.href, instance.id, "the instance URL is correct");
881
+ assert.strictEqual(doc.data.attributes?.name, "Air", "card data is correct");
882
+ });
883
+ instance.name = "Air";
884
+ });
885
+ (0, import_qunit.test)("an instance will auto save when its data changes", async function(assert) {
886
+ assert.expect(2);
887
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
888
+ this.onSave((url, doc) => {
889
+ assert.strictEqual(url.href, instance.id, "the instance URL is correct");
890
+ assert.strictEqual(doc.data.attributes?.name, "Paper", "card data is correct");
891
+ });
892
+ instance.name = "Paper";
893
+ });
894
+ (0, import_qunit.test)("an unsaved instance will auto save when its data changes", async function(assert) {
895
+ assert.expect(2);
896
+ let instance = new PersonDef({ name: "Andrea" });
897
+ await storeService.addWithoutPersisting(instance);
898
+ this.onSave((url, doc) => {
899
+ assert.strictEqual(url.href.split("/").pop(), instance[localId], "the new card url ends with the local id");
900
+ assert.strictEqual(doc.data.attributes?.name, "Air", "card data is correct");
901
+ });
902
+ instance.name = "Air";
903
+ });
904
+ (0, import_qunit.test)("an instance will NOT auto save when its data changes, if the user does not have write permissions", async function(assert) {
905
+ storeService.realm.permissions = () => ({
906
+ get canRead() {
907
+ return true;
908
+ },
909
+ get canWrite() {
910
+ return false;
911
+ }
912
+ });
913
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
914
+ this.onSave(() => {
915
+ assert.ok(false, "should not save");
916
+ });
917
+ instance.name = "Paper";
918
+ assert.strictEqual(instance.name, "Paper");
919
+ let id = instance.id;
920
+ assert.deepEqual(storeService.getSaveState(id), {
921
+ hasUnsavedChanges: true,
922
+ isSaving: false,
923
+ lastSaveError: void 0,
924
+ lastSaved: void 0,
925
+ lastSavedErrorMsg: void 0
926
+ });
927
+ });
928
+ (0, import_qunit.test)("an instance can debounce auto saves", async function(assert) {
929
+ assert.expect(5);
930
+ setCardInOperatorModeState(`${testRealmURL}Person/hassan`, "edit");
931
+ await renderComponent(class TestDriver extends Component {
932
+ static {
933
+ setComponentTemplate(templateFactory({
934
+ "id": "ZD1xwmB+",
935
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
936
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
937
+ "scope": () => [OperatorModeContainer, noop],
938
+ "isStrictMode": true
939
+ }), this);
940
+ }
941
+ });
942
+ let nameInput = `[data-test-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"] input`;
943
+ let typedSoFar = () => find(nameInput)?.value;
944
+ let typedWhenIssued = [];
945
+ let saveLog = [];
946
+ let saveTrace = () => `saves so far: ${saveLog.join(" | ")}`;
947
+ let saveCount = 0;
948
+ this.onSave((url, doc) => {
949
+ saveCount++;
950
+ let savedName = doc.data?.attributes?.name;
951
+ saveLog.push(`#${saveCount} issuedAfter=${JSON.stringify(typedWhenIssued[saveCount - 1])} saved=${JSON.stringify(savedName)}`);
952
+ assert.strictEqual(url.href, `${testRealmURL}Person/hassan`, "correct document is saved");
953
+ switch (saveCount) {
954
+ case 1:
955
+ assert.strictEqual(savedName, "Hassan ", `the initial instance mutation event is saved (${saveTrace()})`);
956
+ break;
957
+ case 2:
958
+ assert.strictEqual(savedName, "Hassan Paper", `the final instance mutation event is saved (${saveTrace()})`);
959
+ break;
960
+ default: assert.ok(false, `unexpected number of saves: ${saveCount} (${saveTrace()})`);
961
+ }
962
+ });
963
+ await withSavesHeldOpen(async (release) => {
964
+ let keystrokes = typeIn(nameInput, " Paper");
965
+ keystrokes.catch(() => {});
966
+ try {
967
+ await Promise.race([keystrokes, waitUntil(() => typedSoFar() === "Hassan Paper", { timeout: 3e3 })]);
968
+ } catch (err) {
969
+ throw new Error(`the keystrokes did not land, input holds ${JSON.stringify(typedSoFar())} (${saveTrace()})`, { cause: err });
970
+ }
971
+ release();
972
+ await keystrokes;
973
+ }, { onSaveIssued: () => typedWhenIssued.push(typedSoFar()) });
974
+ assert.strictEqual(saveCount, 2, `the number of auto-saves is correct (${saveTrace()})`);
975
+ });
976
+ (0, import_qunit.test)("a non-immediate auto save stays in flight for the save-indicator floor", async function(assert) {
977
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
978
+ let id = instance.id;
979
+ let store = storeService;
980
+ let originalPersist = store.persistAndUpdate;
981
+ store.persistAndUpdate = async () => instance;
982
+ try {
983
+ let startedAt = Date.now();
984
+ instance.name = "Paper";
985
+ await waitUntil(() => storeService.getSaveState(id)?.lastSaved, { timeout: 5e3 });
986
+ let heldMs = Date.now() - startedAt;
987
+ assert.ok(heldMs >= 500, `the save is held in flight for the floor (held ${heldMs}ms)`);
988
+ } finally {
989
+ store.persistAndUpdate = originalPersist;
990
+ }
991
+ });
992
+ (0, import_qunit.test)("getSaveState works for initially unsaved instance", async function(assert) {
993
+ let instance = new PersonDef({ name: "Andrea" });
994
+ await storeService.addWithoutPersisting(instance);
995
+ assert.strictEqual(storeService.getSaveState(instance[localId]), void 0, "save state is undefined");
996
+ instance.name = "Air";
997
+ assert.true(storeService.getSaveState(instance[localId])?.hasUnsavedChanges, "hasUnsavedChanges state is correct");
998
+ await waitUntil(() => storeService.getSaveState(instance[localId])?.isSaving, { timeout: 1e4 });
999
+ await waitUntil(() => storeService.getSaveState(instance[localId])?.lastSaved, { timeout: 1e4 });
1000
+ assert.false(storeService.getSaveState(instance[localId])?.isSaving, "isSaving state is correct");
1001
+ assert.false(storeService.getSaveState(instance.id)?.isSaving, "isSaving state is correct (by remote id)");
1002
+ assert.ok(storeService.getSaveState(instance.id)?.lastSaved, "lastSaved state is correct (by remote id)");
1003
+ });
1004
+ (0, import_qunit.test)("can capture error when auto saving", async function(assert) {
1005
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
1006
+ try {
1007
+ globalThis.__emulateServerPatchFailure = true;
1008
+ instance.hasError = true;
1009
+ await waitUntil(() => storeService.getSaveState(`${testRealmURL}Person/hassan`)?.lastSaveError, { timeout: 1e4 });
1010
+ let saveState = storeService.getSaveState(`${testRealmURL}Person/hassan`);
1011
+ assert.ok(saveState.lastSavedErrorMsg?.includes("intentional error thrown"), "error message is correct");
1012
+ } finally {
1013
+ delete globalThis.__emulateServerPatchFailure;
1014
+ }
1015
+ });
1016
+ (0, import_qunit.module)("auto save waits for edits to pause", function(hooks) {
1017
+ let saves;
1018
+ let originalQuietPeriodMs;
1019
+ let originalMaxWaitMs;
1020
+ function recordSave(url, doc) {
1021
+ saves.push({
1022
+ url: url.href,
1023
+ name: doc.data?.attributes?.name
1024
+ });
1025
+ }
1026
+ hooks.beforeEach(function() {
1027
+ saves = [];
1028
+ this.onSave(recordSave);
1029
+ let environment = getService("environment-service");
1030
+ originalQuietPeriodMs = environment.autoSaveQuietPeriodMs;
1031
+ originalMaxWaitMs = environment.autoSaveMaxWaitMs;
1032
+ setAutoSaveTiming(NEVER, NEVER);
1033
+ });
1034
+ hooks.afterEach(function() {
1035
+ let environment = getService("environment-service");
1036
+ environment.autoSaveQuietPeriodMs = originalQuietPeriodMs;
1037
+ environment.autoSaveMaxWaitMs = originalMaxWaitMs;
1038
+ });
1039
+ function setAutoSaveTiming(quietPeriodMs, maxWaitMs) {
1040
+ let environment = getService("environment-service");
1041
+ environment.autoSaveQuietPeriodMs = quietPeriodMs;
1042
+ environment.autoSaveMaxWaitMs = maxWaitMs;
1043
+ }
1044
+ const NEVER = 10 * 6e4;
1045
+ function pause(ms) {
1046
+ return new Promise((resolve) => setTimeout(resolve, ms));
1047
+ }
1048
+ async function waitForSaves(count, message) {
1049
+ try {
1050
+ await waitUntil(() => saves.length >= count, { timeout: 5e3 });
1051
+ } catch (err) {
1052
+ throw new Error(`${message}: expected ${count} save(s), saw ${JSON.stringify(saves)}`, { cause: err });
1053
+ }
1054
+ }
1055
+ function recordWrites() {
1056
+ let virtualNetwork = getService("network").virtualNetwork;
1057
+ let originalFetch = virtualNetwork.fetch;
1058
+ let writes = [];
1059
+ virtualNetwork.fetch = async (input, init) => {
1060
+ let request = input instanceof Request ? input : void 0;
1061
+ let method = init?.method ?? request?.method ?? "GET";
1062
+ if (method === "PATCH" || method === "POST") writes.push({
1063
+ url: request?.url ?? String(input),
1064
+ keepalive: init?.keepalive ?? request?.keepalive ?? false
1065
+ });
1066
+ return await originalFetch.call(virtualNetwork, input, init);
1067
+ };
1068
+ return {
1069
+ writes,
1070
+ restore: () => virtualNetwork.fetch = originalFetch
1071
+ };
1072
+ }
1073
+ function hidePage() {
1074
+ Object.defineProperty(document, "visibilityState", {
1075
+ configurable: true,
1076
+ get: () => "hidden"
1077
+ });
1078
+ try {
1079
+ document.dispatchEvent(new Event("visibilitychange"));
1080
+ } finally {
1081
+ delete document.visibilityState;
1082
+ }
1083
+ }
1084
+ (0, import_qunit.test)("edits are saved once, after they pause", async function(assert) {
1085
+ setAutoSaveTiming(300, NEVER);
1086
+ let id = `${testRealmURL}Person/hassan`;
1087
+ let instance = await storeService.get(id);
1088
+ for (let name of [
1089
+ "H",
1090
+ "Ha",
1091
+ "Has",
1092
+ "Hass",
1093
+ "Hassa"
1094
+ ]) {
1095
+ instance.name = name;
1096
+ await pause(50);
1097
+ }
1098
+ assert.strictEqual(saves.length, 0, "nothing is saved while editing");
1099
+ let saveState = storeService.getSaveState(id);
1100
+ assert.true(saveState.hasUnsavedChanges, "the card has unsaved changes");
1101
+ assert.false(saveState.isSaving, "the card is not saving yet");
1102
+ assert.strictEqual(saveState.lastSavedErrorMsg, "Unsaved changes", "the indicator reports unsaved changes");
1103
+ await waitForSaves(1, "the edits are saved once they pause");
1104
+ await storeService.flushSaves();
1105
+ assert.deepEqual(saves, [{
1106
+ url: id,
1107
+ name: "Hassa"
1108
+ }], "one save carries the last edit");
1109
+ assert.false(storeService.getSaveState(id).hasUnsavedChanges, "nothing is left unsaved");
1110
+ assert.ok(storeService.getSaveState(id).lastSavedErrorMsg?.startsWith("Saved"), "the indicator reports the save");
1111
+ });
1112
+ (0, import_qunit.test)("editing without a pause is saved at the maximum wait", async function(assert) {
1113
+ setAutoSaveTiming(300, 600);
1114
+ let id = `${testRealmURL}Person/hassan`;
1115
+ let instance = await storeService.get(id);
1116
+ let maxWaitMs = 600;
1117
+ let edits = 30;
1118
+ let startedAt = Date.now();
1119
+ for (let i = 1; i <= edits; i++) {
1120
+ instance.name = `Hassan ${i}`;
1121
+ await pause(100);
1122
+ }
1123
+ let editingMs = Date.now() - startedAt;
1124
+ let savedWhileEditing = saves.length;
1125
+ await storeService.flushSaves();
1126
+ assert.ok(savedWhileEditing >= 1, `edits are saved while editing goes on (${savedWhileEditing} saved)`);
1127
+ let bound = Math.ceil(editingMs / maxWaitMs) + 1;
1128
+ assert.ok(saves.length <= bound, `${edits} edits over ${editingMs}ms take at most ${bound} saves (${saves.length} saved)`);
1129
+ assert.ok(saves.length < edits / 3, `${edits} edits take far fewer saves than edits (${saves.length} saved)`);
1130
+ assert.strictEqual(saves[saves.length - 1]?.name, `Hassan ${edits}`, "the last save carries the last edit");
1131
+ });
1132
+ (0, import_qunit.test)("an edit made while its save runs stays unsaved until the next save", async function(assert) {
1133
+ let id = `${testRealmURL}Person/hassan`;
1134
+ let instance = await storeService.get(id);
1135
+ await withSavesHeldOpen(async (release) => {
1136
+ instance.name = "Paper";
1137
+ document.body.dispatchEvent(new FocusEvent("focusout", { bubbles: true }));
1138
+ await waitUntil(() => storeService.getSaveState(id)?.isSaving);
1139
+ instance.name = "Paper Hassan";
1140
+ release();
1141
+ await waitUntil(() => !storeService.getSaveState(id)?.isSaving);
1142
+ let saveState = storeService.getSaveState(id);
1143
+ assert.true(saveState.hasUnsavedChanges, "the edit made during the save is still unsaved");
1144
+ assert.strictEqual(saveState.lastSavedErrorMsg, "Unsaved changes", "the indicator does not report the edit as saved");
1145
+ });
1146
+ await storeService.flushSaves();
1147
+ assert.deepEqual(saves.map((s) => s.name), ["Paper", "Paper Hassan"], "both edits are saved, in order");
1148
+ assert.false(storeService.getSaveState(id).hasUnsavedChanges);
1149
+ });
1150
+ (0, import_qunit.test)("a pending save is sent when the last reference to its card is dropped", async function(assert) {
1151
+ let id = `${testRealmURL}Person/hassan`;
1152
+ storeService.addReference(id);
1153
+ await storeService.flush();
1154
+ let instance = storeService.peek(id);
1155
+ instance.name = "Paper";
1156
+ storeService.dropReference(id);
1157
+ await waitForSaves(1, "dropping the last reference sends the save");
1158
+ assert.deepEqual(saves, [{
1159
+ url: id,
1160
+ name: "Paper"
1161
+ }]);
1162
+ await storeService.flushSaves();
1163
+ assert.strictEqual(storeService.getReferenceCount(id), 0, "the save's hold on the card is released once it lands");
1164
+ });
1165
+ (0, import_qunit.test)("a pending save is not sent early while something still shows its card", async function(assert) {
1166
+ let id = `${testRealmURL}Person/hassan`;
1167
+ storeService.addReference(id);
1168
+ storeService.addReference(id);
1169
+ await storeService.flush();
1170
+ let instance = storeService.peek(id);
1171
+ instance.name = "Paper";
1172
+ storeService.dropReference(id);
1173
+ await pause(1e3);
1174
+ assert.strictEqual(saves.length, 0, "the save keeps waiting");
1175
+ storeService.dropReference(id);
1176
+ await waitForSaves(1, "dropping the last reference sends the save");
1177
+ assert.deepEqual(saves, [{
1178
+ url: id,
1179
+ name: "Paper"
1180
+ }]);
1181
+ });
1182
+ (0, import_qunit.test)("garbage collection keeps a card whose save is pending", async function(assert) {
1183
+ let id = `${testRealmURL}Person/hassan`;
1184
+ let controlId = `${testRealmURL}Person/jade`;
1185
+ let instance = await storeService.get(id);
1186
+ let control = await storeService.get(controlId);
1187
+ assert.strictEqual(storeService.getReferenceCount(id), 0);
1188
+ assert.strictEqual(storeService.getReferenceCount(controlId), 0);
1189
+ instance.name = "Paper";
1190
+ forceGC();
1191
+ assert.strictEqual(storeService.peek(controlId), void 0, "an unreferenced card without a pending save is collected");
1192
+ assert.notStrictEqual(control, void 0);
1193
+ assert.strictEqual(storeService.peek(id), instance, "the card with a pending save is kept");
1194
+ await storeService.flushSaves();
1195
+ assert.deepEqual(saves, [{
1196
+ url: id,
1197
+ name: "Paper"
1198
+ }]);
1199
+ });
1200
+ (0, import_qunit.test)("flushSaves sends pending saves and waits for them", async function(assert) {
1201
+ let id = `${testRealmURL}Person/hassan`;
1202
+ let instance = await storeService.get(id);
1203
+ instance.name = "Paper";
1204
+ await storeService.flushSaves();
1205
+ assert.deepEqual(saves, [{
1206
+ url: id,
1207
+ name: "Paper"
1208
+ }]);
1209
+ assert.false(storeService.hasUnsavedEdits);
1210
+ });
1211
+ (0, import_qunit.test)("ending the session drops saves still waiting for typing to pause", async function(assert) {
1212
+ let id = `${testRealmURL}Person/hassan`;
1213
+ let instance = await storeService.get(id);
1214
+ instance.name = "Paper";
1215
+ storeService.resetState();
1216
+ storeService._onSave(recordSave);
1217
+ await pause(1e3);
1218
+ assert.deepEqual(saves, [], "nothing is written after the session ends");
1219
+ assert.false(storeService.hasUnsavedEdits, "nothing is left pending");
1220
+ });
1221
+ (0, import_qunit.test)("a save queued behind a running one does not write once the session ends", async function(assert) {
1222
+ let id = `${testRealmURL}Person/hassan`;
1223
+ let instance = await storeService.get(id);
1224
+ await withSavesHeldOpen(async (release) => {
1225
+ instance.name = "Paper";
1226
+ storeService.flushSaves();
1227
+ await waitUntil(() => storeService.getSaveState(id)?.isSaving);
1228
+ instance.name = "Paper Hassan";
1229
+ storeService.flushSaves();
1230
+ storeService.resetState();
1231
+ storeService._onSave(recordSave);
1232
+ release();
1233
+ await waitUntil(() => !storeService.hasUnsavedEdits, { timeout: 5e3 });
1234
+ });
1235
+ assert.deepEqual(saves.map((s) => s.name), ["Paper"], "only the save that started before the session ended is written");
1236
+ });
1237
+ (0, import_qunit.test)("logout saves pending edits before the session ends", async function(assert) {
1238
+ let id = `${testRealmURL}Person/hassan`;
1239
+ let instance = await storeService.get(id);
1240
+ instance.name = "Paper";
1241
+ let matrixService = getService("matrix-service");
1242
+ let originalClearAuth = matrixService.clearAuth;
1243
+ let originalResetState = matrixService.resetState;
1244
+ let savedWhenAuthCleared;
1245
+ matrixService.clearAuth = () => {
1246
+ savedWhenAuthCleared = [...saves];
1247
+ throw new Error("stop logout here");
1248
+ };
1249
+ matrixService.resetState = () => {};
1250
+ try {
1251
+ await matrixService.logout({ skipIndexTransition: true });
1252
+ } finally {
1253
+ matrixService.clearAuth = originalClearAuth;
1254
+ matrixService.resetState = originalResetState;
1255
+ }
1256
+ assert.deepEqual(savedWhenAuthCleared, [{
1257
+ url: id,
1258
+ name: "Paper"
1259
+ }], "the edit is saved before auth is cleared");
1260
+ });
1261
+ (0, import_qunit.test)("resetting the store cache sends pending saves", async function(assert) {
1262
+ let id = `${testRealmURL}Person/hassan`;
1263
+ let instance = await storeService.get(id);
1264
+ instance.name = "Paper";
1265
+ storeService.resetCache();
1266
+ await waitForSaves(1, "the reset sends the save");
1267
+ assert.deepEqual(saves, [{
1268
+ url: id,
1269
+ name: "Paper"
1270
+ }]);
1271
+ await storeService.flushSaves();
1272
+ });
1273
+ (0, import_qunit.test)("hiding the page sends pending saves as requests that outlive the page", async function(assert) {
1274
+ let id = `${testRealmURL}Person/hassan`;
1275
+ let instance = await storeService.get(id);
1276
+ instance.name = "Paper";
1277
+ let { writes, restore } = recordWrites();
1278
+ try {
1279
+ hidePage();
1280
+ await waitForSaves(1, "hiding the page sends the save");
1281
+ } finally {
1282
+ restore();
1283
+ }
1284
+ assert.deepEqual(saves, [{
1285
+ url: id,
1286
+ name: "Paper"
1287
+ }]);
1288
+ assert.deepEqual(writes, [{
1289
+ url: id,
1290
+ keepalive: true
1291
+ }]);
1292
+ });
1293
+ (0, import_qunit.test)("pagehide sends pending saves as requests that outlive the page", async function(assert) {
1294
+ let id = `${testRealmURL}Person/hassan`;
1295
+ let instance = await storeService.get(id);
1296
+ instance.name = "Paper";
1297
+ let { writes, restore } = recordWrites();
1298
+ try {
1299
+ window.dispatchEvent(new PageTransitionEvent("pagehide"));
1300
+ await waitForSaves(1, "pagehide sends the save");
1301
+ await storeService.flushSaves();
1302
+ } finally {
1303
+ restore();
1304
+ }
1305
+ assert.deepEqual(saves, [{
1306
+ url: id,
1307
+ name: "Paper"
1308
+ }]);
1309
+ assert.deepEqual(writes, [{
1310
+ url: id,
1311
+ keepalive: true
1312
+ }]);
1313
+ });
1314
+ (0, import_qunit.test)("saves past the keepalive budget are still sent, without keepalive", async function(assert) {
1315
+ let ids = [`${testRealmURL}Person/hassan`, `${testRealmURL}Person/jade`];
1316
+ let longName = "x".repeat(4e4);
1317
+ for (let id of ids) {
1318
+ let instance = await storeService.get(id);
1319
+ instance.name = longName;
1320
+ }
1321
+ let { writes, restore } = recordWrites();
1322
+ try {
1323
+ window.dispatchEvent(new PageTransitionEvent("pagehide"));
1324
+ await waitForSaves(2, "pagehide sends both saves");
1325
+ await storeService.flushSaves();
1326
+ } finally {
1327
+ restore();
1328
+ }
1329
+ assert.deepEqual(saves.map((s) => s.url).sort(), [...ids].sort(), "both cards are saved");
1330
+ assert.deepEqual(writes.map((w) => w.keepalive).sort(), [false, true], "one save fits the budget and the other is sent as an ordinary request");
1331
+ });
1332
+ (0, import_qunit.test)("an edit after a flush gives up still waits for typing to pause", async function(assert) {
1333
+ let id = `${testRealmURL}Person/hassan`;
1334
+ let jade = `${testRealmURL}Person/jade`;
1335
+ let instance = await storeService.get(id);
1336
+ let other = await storeService.get(jade);
1337
+ await withSavesHeldOpen(async (release) => {
1338
+ instance.name = "Paper";
1339
+ await storeService.flushSaves({ timeoutMs: 100 });
1340
+ assert.true(storeService.hasUnsavedEdits, "the held save is running");
1341
+ other.name = "Jade Paper";
1342
+ release();
1343
+ await waitUntil(() => saves.length === 1, { timeout: 5e3 });
1344
+ await pause(500);
1345
+ });
1346
+ assert.deepEqual(saves.map((s) => s.name), ["Paper"], "the later edit is not sent when the flush's save lands");
1347
+ await storeService.flushSaves();
1348
+ assert.deepEqual(saves.map((s) => s.name), ["Paper", "Jade Paper"]);
1349
+ });
1350
+ (0, import_qunit.test)("focus leaving a field sends pending saves", async function(assert) {
1351
+ let id = `${testRealmURL}Person/hassan`;
1352
+ let instance = await storeService.get(id);
1353
+ instance.name = "Paper";
1354
+ document.body.dispatchEvent(new FocusEvent("focusout", { bubbles: true }));
1355
+ await waitForSaves(1, "focus leaving sends the save");
1356
+ assert.deepEqual(saves, [{
1357
+ url: id,
1358
+ name: "Paper"
1359
+ }]);
1360
+ });
1361
+ (0, import_qunit.test)("closing a card in the stack sends the save its edit is waiting on", async function(assert) {
1362
+ let id = `${testRealmURL}Person/hassan`;
1363
+ setCardInOperatorModeState(id, "edit");
1364
+ await renderComponent(class TestDriver extends Component {
1365
+ static {
1366
+ setComponentTemplate(templateFactory({
1367
+ "id": "ZD1xwmB+",
1368
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
1369
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
1370
+ "scope": () => [OperatorModeContainer, noop],
1371
+ "isStrictMode": true
1372
+ }), this);
1373
+ }
1374
+ });
1375
+ let input = find(`[data-test-stack-card="${id}"] [data-test-field="name"] input`);
1376
+ input.value = "Hassan Paper";
1377
+ input.dispatchEvent(new Event("input", { bubbles: true }));
1378
+ assert.strictEqual(saves.length, 0, "the edit waits to be saved");
1379
+ let closed = click(`[data-test-stack-card="${id}"] [data-test-close-button]`);
1380
+ await waitForSaves(1, "closing the card sends the save");
1381
+ await closed;
1382
+ assert.deepEqual(saves, [{
1383
+ url: id,
1384
+ name: "Hassan Paper"
1385
+ }]);
1386
+ });
1387
+ });
1388
+ (0, import_qunit.test)("can delete card from the store", async function(assert) {
1389
+ storeService.addReference(`${testRealmURL}Person/boris`);
1390
+ await storeService.flush();
1391
+ let instance = storeService.peek(`${testRealmURL}Person/boris`);
1392
+ await storeService.delete(`${testRealmURL}Person/boris`);
1393
+ assert.strictEqual(storeService.peek(instance.id), void 0, "the instance is no longer in the store");
1394
+ assert.strictEqual(storeService.peek(instance[localId]), void 0, "the instance is no longer in the store (via local id)");
1395
+ let file = await testRealmAdapter.openFile(`Person/boris.json`);
1396
+ assert.strictEqual(file, void 0, "file no longer exists");
1397
+ });
1398
+ (0, import_qunit.test)("subscribeToCardInvalidation fires the callback when the card is deleted", async function(assert) {
1399
+ storeService.addReference(`${testRealmURL}Person/boris`);
1400
+ await storeService.flush();
1401
+ let fired = 0;
1402
+ let unsubscribe = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
1403
+ fired += 1;
1404
+ });
1405
+ await storeService.delete(`${testRealmURL}Person/boris`);
1406
+ assert.strictEqual(fired, 1, "the invalidation subscriber fires exactly once on delete");
1407
+ unsubscribe();
1408
+ });
1409
+ (0, import_qunit.test)("subscribeToCardInvalidation unsubscribe stops firing the callback", async function(assert) {
1410
+ storeService.addReference(`${testRealmURL}Person/boris`);
1411
+ await storeService.flush();
1412
+ let fired = 0;
1413
+ storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
1414
+ fired += 1;
1415
+ })();
1416
+ await storeService.delete(`${testRealmURL}Person/boris`);
1417
+ assert.strictEqual(fired, 0, "no callbacks fire after unsubscribe");
1418
+ });
1419
+ (0, import_qunit.test)("a synchronously throwing invalidation subscriber does not break siblings", async function(assert) {
1420
+ storeService.addReference(`${testRealmURL}Person/boris`);
1421
+ await storeService.flush();
1422
+ let originalError = console.error;
1423
+ let captured = [];
1424
+ console.error = (...args) => {
1425
+ if (typeof args[0] === "string" && args[0].includes("card invalidation subscriber")) captured.push(args);
1426
+ else originalError(...args);
1427
+ };
1428
+ let secondFired = 0;
1429
+ let unsubscribeA = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
1430
+ throw new Error("intentional sync throw from invalidation subscriber");
1431
+ });
1432
+ let unsubscribeB = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
1433
+ secondFired += 1;
1434
+ });
1435
+ try {
1436
+ await storeService.delete(`${testRealmURL}Person/boris`);
1437
+ assert.strictEqual(secondFired, 1, "the second subscriber still runs after the first one throws");
1438
+ assert.strictEqual(captured.length, 1, "the synchronous throw is reported via console.error exactly once");
1439
+ } finally {
1440
+ unsubscribeA();
1441
+ unsubscribeB();
1442
+ console.error = originalError;
1443
+ }
1444
+ });
1445
+ (0, import_qunit.test)("an async-rejecting invalidation subscriber does not break siblings and does not surface as an unhandled rejection", async function(assert) {
1446
+ storeService.addReference(`${testRealmURL}Person/boris`);
1447
+ await storeService.flush();
1448
+ let originalError = console.error;
1449
+ let captured = [];
1450
+ console.error = (...args) => {
1451
+ if (typeof args[0] === "string" && args[0].includes("card invalidation subscriber")) captured.push(args);
1452
+ else originalError(...args);
1453
+ };
1454
+ let secondFired = 0;
1455
+ let unsubscribeA = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, async () => {
1456
+ await Promise.resolve();
1457
+ throw new Error("intentional async rejection from invalidation subscriber");
1458
+ });
1459
+ let unsubscribeB = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
1460
+ secondFired += 1;
1461
+ });
1462
+ try {
1463
+ await storeService.delete(`${testRealmURL}Person/boris`);
1464
+ await settled();
1465
+ assert.strictEqual(secondFired, 1, "the second subscriber still runs alongside the async-rejecting one");
1466
+ assert.strictEqual(captured.length, 1, "the async rejection is reported via console.error exactly once");
1467
+ } finally {
1468
+ unsubscribeA();
1469
+ unsubscribeB();
1470
+ console.error = originalError;
1471
+ }
1472
+ });
1473
+ (0, import_qunit.test)("can patch an instance", async function(assert) {
1474
+ let instance = await storeService.patch(`${testRealmURL}Person/hassan`, {
1475
+ attributes: { name: "Hassan Updated" },
1476
+ relationships: {
1477
+ bestFriend: { links: { self: `${testRealmURL}Person/jade` } },
1478
+ "friends.0": { links: { self: `${testRealmURL}Person/germaine` } }
1479
+ }
1480
+ });
1481
+ let peekedInstance = storeService.peek(`${testRealmURL}Person/hassan`);
1482
+ let jade = storeService.peek(`${testRealmURL}Person/jade`);
1483
+ let germaine = storeService.peek(`${testRealmURL}Person/germaine`);
1484
+ assert.strictEqual(peekedInstance, instance, "the patched instance is in the store");
1485
+ assert.ok(isCardInstance(jade), "jade is in the store");
1486
+ assert.ok(isCardInstance(germaine), "germaine is in the store");
1487
+ assert.strictEqual(instance.name, "Hassan Updated", "the contains field was patched");
1488
+ assert.strictEqual(instance.bestFriend, jade, "the linksTo field was patched");
1489
+ assert.deepEqual(instance.friends, [germaine], "the linksToMany field was patched");
1490
+ });
1491
+ (0, import_qunit.test)("a patch that gives a primitive field an object replaces its value", async function(assert) {
1492
+ await testRealm.write("Settings/one.json", JSON.stringify({ data: {
1493
+ type: "card",
1494
+ attributes: {
1495
+ cardInfo: {
1496
+ name: "Settings",
1497
+ summary: "Kept"
1498
+ },
1499
+ config: {
1500
+ approver: "@mae:localhost",
1501
+ retired: true
1502
+ }
1503
+ },
1504
+ meta: { adoptsFrom: {
1505
+ module: "@cardstack/base/realm-config",
1506
+ name: "RealmConfig"
1507
+ } }
1508
+ } }));
1509
+ let id = `${testRealmURL}Settings/one`;
1510
+ let instance = await storeService.patch(id, { attributes: {
1511
+ cardInfo: { name: "Renamed" },
1512
+ config: { approvers: "@mae:localhost" }
1513
+ } });
1514
+ assert.deepEqual(instance.config, { approvers: "@mae:localhost" }, "the instance holds the map the patch sent");
1515
+ let file = await testRealmAdapter.openFile("Settings/one.json");
1516
+ let { attributes } = JSON.parse(file.content).data;
1517
+ assert.deepEqual(attributes.config, { approvers: "@mae:localhost" }, "and so does the saved file, without the renamed or dropped keys");
1518
+ assert.strictEqual(attributes.cardInfo.summary, "Kept", "the compound field keeps the nested value the patch leaves out");
1519
+ });
1520
+ (0, import_qunit.test)("resolving a linksTo lazily issues no save", async function(assert) {
1521
+ let hassanId = `${testRealmURL}Person/hassan`;
1522
+ await testRealm.write("Person/ghost-friend.json", JSON.stringify({ data: {
1523
+ attributes: { name: "Ghost" },
1524
+ meta: { adoptsFrom: {
1525
+ module: testRRI("person"),
1526
+ name: "Person"
1527
+ } }
1528
+ } }));
1529
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
1530
+ attributes: { name: "Hassan" },
1531
+ relationships: { bestFriend: { links: { self: `${testRealmURL}Person/ghost-friend` } } },
1532
+ meta: { adoptsFrom: {
1533
+ module: testRRI("person"),
1534
+ name: "Person"
1535
+ } }
1536
+ } }));
1537
+ let cardService = getService("card-service");
1538
+ let fetchJSON = cardService.fetchJSON.bind(cardService);
1539
+ let intercepted = 0;
1540
+ cardService.fetchJSON = async (url, args) => {
1541
+ let doc = await fetchJSON(url, args);
1542
+ if (String(url).replace(/\.json$/, "") === hassanId) {
1543
+ intercepted++;
1544
+ delete doc?.included;
1545
+ }
1546
+ return doc;
1547
+ };
1548
+ let saved = [];
1549
+ this.onSave((url) => {
1550
+ saved.push(url.href);
1551
+ });
1552
+ try {
1553
+ let instance = await storeService.get(hassanId);
1554
+ assert.ok(intercepted > 0, "the card fetch was intercepted");
1555
+ assert.strictEqual(instance.bestFriend, void 0, "the link is not loaded yet, so reading it takes the lazy path");
1556
+ await storeService.flush();
1557
+ await settled();
1558
+ assert.strictEqual(instance.bestFriend?.name, "Ghost", "the lazy load resolved the target and assigned it to the field");
1559
+ assert.deepEqual(saved, [], "no save was issued while loading");
1560
+ } finally {
1561
+ cardService.fetchJSON = fetchJSON;
1562
+ }
1563
+ });
1564
+ (0, import_qunit.test)("resolving a linksToMany lazily issues no save", async function(assert) {
1565
+ let hassanId = `${testRealmURL}Person/hassan`;
1566
+ await testRealm.write("Person/ghost-friend.json", JSON.stringify({ data: {
1567
+ attributes: { name: "Ghost" },
1568
+ meta: { adoptsFrom: {
1569
+ module: testRRI("person"),
1570
+ name: "Person"
1571
+ } }
1572
+ } }));
1573
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
1574
+ attributes: { name: "Hassan" },
1575
+ relationships: { "friends.0": { links: { self: `${testRealmURL}Person/ghost-friend` } } },
1576
+ meta: { adoptsFrom: {
1577
+ module: testRRI("person"),
1578
+ name: "Person"
1579
+ } }
1580
+ } }));
1581
+ let cardService = getService("card-service");
1582
+ let fetchJSON = cardService.fetchJSON.bind(cardService);
1583
+ let intercepted = 0;
1584
+ cardService.fetchJSON = async (url, args) => {
1585
+ let doc = await fetchJSON(url, args);
1586
+ if (String(url).replace(/\.json$/, "") === hassanId) {
1587
+ intercepted++;
1588
+ delete doc?.included;
1589
+ }
1590
+ return doc;
1591
+ };
1592
+ let saved = [];
1593
+ this.onSave((url) => {
1594
+ saved.push(url.href);
1595
+ });
1596
+ try {
1597
+ let instance = await storeService.get(hassanId);
1598
+ assert.ok(intercepted > 0, "the card fetch was intercepted");
1599
+ assert.deepEqual(instance.friends.map((f) => f?.name), [void 0], "the element is not loaded yet, so reading it takes the lazy path");
1600
+ await storeService.flush();
1601
+ await settled();
1602
+ assert.deepEqual(instance.friends.map((f) => f?.name), ["Ghost"], "the lazy load resolved the target into its slot");
1603
+ assert.deepEqual(saved, [], "no save was issued while loading");
1604
+ } finally {
1605
+ cardService.fetchJSON = fetchJSON;
1606
+ }
1607
+ });
1608
+ (0, import_qunit.test)("a concurrent field write during store.patch is not clobbered by the patch’s stale snapshot", async function(assert) {
1609
+ let targetId = `${testRealmURL}Person/hassan`;
1610
+ let instance = await storeService.get(targetId);
1611
+ let gate = new Deferred();
1612
+ let enteredGate = new Deferred();
1613
+ let originalLoadPatchedInstances = storeService.loadPatchedInstances;
1614
+ storeService.loadPatchedInstances = async function(...args) {
1615
+ let result = await originalLoadPatchedInstances.apply(this, args);
1616
+ enteredGate.fulfill();
1617
+ await gate.promise;
1618
+ return result;
1619
+ };
1620
+ try {
1621
+ let patchPromise = storeService.patch(targetId, { relationships: { bestFriend: { links: { self: `${testRealmURL}Person/jade` } } } });
1622
+ await enteredGate.promise;
1623
+ instance.name = "Race Winner";
1624
+ gate.fulfill();
1625
+ await patchPromise;
1626
+ } finally {
1627
+ storeService.loadPatchedInstances = originalLoadPatchedInstances;
1628
+ }
1629
+ assert.strictEqual(instance.name, "Race Winner", "the concurrent field write is not clobbered by the patch's stale snapshot");
1630
+ assert.strictEqual(instance.bestFriend?.id, `${testRealmURL}Person/jade`, "the patch itself was still applied");
1631
+ });
1632
+ (0, import_qunit.test)("a create gives the instance a remote identity the rest of the store can use", async function(assert) {
1633
+ let instance = new PersonDef({ name: "Sequence" });
1634
+ let instanceLocalId = instance[localId];
1635
+ let subscriptions = storeService.subscriptions;
1636
+ assert.false(subscriptions.has(testRealmURL), "the realm is not subscribed before the create");
1637
+ let result = await storeService.persistAndUpdate(instance);
1638
+ assert.true(isCardInstance(result), "the create resolved to the instance");
1639
+ assert.ok(instance.id?.startsWith(testRealmURL), "the instance took a remote id in the realm");
1640
+ assert.strictEqual(storeService.peek(instanceLocalId), instance, "the local id still resolves to this instance");
1641
+ assert.strictEqual(storeService.peek(instance.id), instance, "the remote id resolves to the same instance");
1642
+ assert.true(subscriptions.has(testRealmURL), "the store is listening for the realm's index events");
1643
+ let cardPath = `${instance.id.substring(testRealmURL.length)}.json`;
1644
+ assert.ok(await testRealmAdapter.openFile(cardPath), "the realm holds the created card");
1645
+ instance.name = "Sequence Edited";
1646
+ await waitUntil(() => storeService.getSaveState(instanceLocalId)?.lastSaved, { timeout: 1e4 });
1647
+ await settled();
1648
+ let file = await testRealmAdapter.openFile(cardPath);
1649
+ assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Sequence Edited", "an edit after the create autosaves to the realm");
1650
+ });
1651
+ (0, import_qunit.test)("a small new card saves even when its resident linked graph would overflow the size limit if inlined", async function(assert) {
1652
+ let environmentService = getService("environment-service");
1653
+ let originalMaxSize = environmentService.cardSizeLimitBytes;
1654
+ try {
1655
+ let bigFriend = new PersonDef({ name: "x".repeat(6e3) });
1656
+ let savedFriend = await storeService.persistAndUpdate(bigFriend);
1657
+ assert.true(isCardInstance(savedFriend), "the large linked card saved");
1658
+ environmentService.cardSizeLimitBytes = 2500;
1659
+ let instance = new PersonDef({ name: "Small" });
1660
+ instance.bestFriend = bigFriend;
1661
+ let result = await storeService.persistAndUpdate(instance);
1662
+ assert.true(isCardInstance(result), "a new card whose own document is under the limit saves regardless of how large a graph it links to — the check measures what the realm stores, not the tab's loaded `included`");
1663
+ let cardPath = `${instance.id.substring(testRealmURL.length)}.json`;
1664
+ assert.ok(await testRealmAdapter.openFile(cardPath), "the realm holds the created card");
1665
+ } finally {
1666
+ environmentService.cardSizeLimitBytes = originalMaxSize;
1667
+ }
1668
+ });
1669
+ (0, import_qunit.test)("includedScope controls which link targets the serializer builds", async function(assert) {
1670
+ let cardService = getService("card-service");
1671
+ let api = await cardService.getAPI();
1672
+ let saved = new PersonDef({ name: "Saved" });
1673
+ await storeService.persistAndUpdate(saved);
1674
+ let unsaved = new PersonDef({ name: "Unsaved" });
1675
+ let instance = new PersonDef({ name: "Consumer" });
1676
+ instance.bestFriend = saved;
1677
+ instance.friends = [unsaved];
1678
+ let all = api.serializeCard(instance, {
1679
+ useAbsoluteURL: true,
1680
+ includedScope: "all"
1681
+ });
1682
+ assert.ok((all.included ?? []).find((r) => r.id === saved.id), "'all' serializes saved targets into included");
1683
+ assert.ok((all.included ?? []).find((r) => r.lid === unsaved[localId]), "'all' serializes local targets into included");
1684
+ let local = api.serializeCard(instance, {
1685
+ useAbsoluteURL: true,
1686
+ includedScope: "local"
1687
+ });
1688
+ assert.notOk((local.included ?? []).find((r) => r.id === saved.id), "'local' does not serialize saved targets");
1689
+ assert.ok((local.included ?? []).find((r) => r.lid === unsaved[localId]), "'local' serializes local targets — the write's co-creation manifest");
1690
+ let none = api.serializeCard(instance, {
1691
+ useAbsoluteURL: true,
1692
+ includedScope: "none"
1693
+ });
1694
+ assert.strictEqual(none.included, void 0, "'none' builds no included at all");
1695
+ assert.deepEqual(local.data, all.data, "'local' leaves the primary resource identical to 'all'");
1696
+ assert.deepEqual(none.data, all.data, "'none' leaves the primary resource identical to 'all'");
1697
+ let viaCardService = await cardService.serializeCard(instance, {
1698
+ useAbsoluteURL: true,
1699
+ withLocalResourcesIncluded: true
1700
+ });
1701
+ assert.deepEqual(viaCardService, local, "withLocalResourcesIncluded serializes at the 'local' scope");
1702
+ });
1703
+ (0, import_qunit.test)("an oversized unsaved link created alongside a card still fails the size check", async function(assert) {
1704
+ let environmentService = getService("environment-service");
1705
+ let originalMaxSize = environmentService.cardSizeLimitBytes;
1706
+ try {
1707
+ environmentService.cardSizeLimitBytes = 2500;
1708
+ let bigUnsaved = new PersonDef({ name: "x".repeat(6e3) });
1709
+ let instance = new PersonDef({ name: "Small" });
1710
+ instance.bestFriend = bigUnsaved;
1711
+ let result = await storeService.persistAndUpdate(instance);
1712
+ assert.false(isCardInstance(result), "the save is refused: the unsaved link is co-created as its own file and is over the ceiling");
1713
+ assert.ok(String(result?.message).includes("exceeds maximum allowed size"), `the error names the size limit (got: ${result?.message})`);
1714
+ } finally {
1715
+ environmentService.cardSizeLimitBytes = originalMaxSize;
1716
+ }
1717
+ });
1718
+ (0, import_qunit.test)("a save overlapping a create PATCHes instead of issuing a second POST", async function(assert) {
1719
+ let instance = new PersonDef({ name: "Overlap" });
1720
+ await storeService.addWithoutPersisting(instance);
1721
+ let cardService = getService("card-service");
1722
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
1723
+ let methods = [];
1724
+ let reachedPost = new Deferred();
1725
+ let releasePost = new Deferred();
1726
+ cardService.fetchJSON = async (url, args) => {
1727
+ if (args?.method !== "POST" && args?.method !== "PATCH") return originalFetchJSON(url, args);
1728
+ methods.push(args.method);
1729
+ if (args.method === "POST") {
1730
+ reachedPost.fulfill();
1731
+ await releasePost.promise;
1732
+ }
1733
+ return originalFetchJSON(url, args);
1734
+ };
1735
+ try {
1736
+ let creating = storeService.persistAndUpdate(instance);
1737
+ let reachedPostFirst = await Promise.race([reachedPost.promise.then(() => true), creating.then(() => false)]);
1738
+ assert.true(reachedPostFirst, `the create reached its POST (resolved early as: ${JSON.stringify(await Promise.race([creating, Promise.resolve("still in flight")]))})`);
1739
+ let overlapping = storeService.persistAndUpdate(instance);
1740
+ releasePost.fulfill();
1741
+ await Promise.all([creating, overlapping]);
1742
+ } finally {
1743
+ releasePost.fulfill();
1744
+ delete cardService.fetchJSON;
1745
+ }
1746
+ await settled();
1747
+ assert.deepEqual(methods, ["POST", "PATCH"], "the overlapping save waited for the remote id and updated the created card");
1748
+ assert.ok(await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`), "the realm holds the created card");
1749
+ });
1750
+ function holdCreateResponse(held, opts) {
1751
+ let cardService = getService("card-service");
1752
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
1753
+ let writes = [];
1754
+ let stored = new Deferred();
1755
+ let release = new Deferred();
1756
+ cardService.fetchJSON = async (url, args) => {
1757
+ if (args?.method !== "POST" && args?.method !== "PATCH") return originalFetchJSON(url, args);
1758
+ let body = JSON.parse(args.body);
1759
+ writes.push({
1760
+ method: args.method,
1761
+ body
1762
+ });
1763
+ if (args.method !== "POST" || body.data.lid !== held[localId]) return originalFetchJSON(url, args);
1764
+ let response = await originalFetchJSON(url, args);
1765
+ stored.fulfill();
1766
+ await release.promise;
1767
+ if (opts?.fail) throw new Error("the create response never arrived");
1768
+ return response;
1769
+ };
1770
+ return {
1771
+ writes,
1772
+ stored: stored.promise,
1773
+ release: () => release.fulfill(),
1774
+ restore() {
1775
+ release.fulfill();
1776
+ delete cardService.fetchJSON;
1777
+ }
1778
+ };
1779
+ }
1780
+ function includedLids(body) {
1781
+ return (body.included ?? []).flatMap((resource) => "lid" in resource && resource.lid ? [resource.lid] : []);
1782
+ }
1783
+ (0, import_qunit.test)("a save does not send a linked card whose create is still in flight as a card to create", async function(assert) {
1784
+ let friend = new PersonDef({ name: "Friend" });
1785
+ await storeService.addWithoutPersisting(friend);
1786
+ let person = new PersonDef({ name: "Person" });
1787
+ person.bestFriend = friend;
1788
+ await storeService.addWithoutPersisting(person);
1789
+ let hold = holdCreateResponse(friend);
1790
+ let personResult;
1791
+ try {
1792
+ let creatingFriend = storeService.persistAndUpdate(friend);
1793
+ await hold.stored;
1794
+ let savingPerson = storeService.persistAndUpdate(person);
1795
+ let personSettledWhileFriendHeld = await Promise.race([savingPerson.then(() => true), new Promise((r) => setTimeout(() => r(false), 500))]);
1796
+ assert.false(personSettledWhileFriendHeld, "the save waits while the linked card's create is unanswered");
1797
+ assert.deepEqual(hold.writes.map((w) => w.method), ["POST"], "nothing but the linked card's own create went out while it was unanswered");
1798
+ hold.release();
1799
+ [, personResult] = await Promise.all([creatingFriend, savingPerson]);
1800
+ } finally {
1801
+ hold.restore();
1802
+ }
1803
+ await settled();
1804
+ assert.true(isCardInstance(personResult), `the save succeeded (resolved as: ${JSON.stringify(personResult)})`);
1805
+ let personWrite = hold.writes.find((w) => w.body.data.lid === person[localId]);
1806
+ assert.ok(personWrite, "the card linking to it was saved");
1807
+ assert.deepEqual(includedLids(personWrite.body), [], "the save carried no card to create");
1808
+ assert.strictEqual(personWrite.body.data.relationships?.bestFriend?.links?.self, friend.id, "the save linked to the id the realm assigned the linked card");
1809
+ let file = await testRealmAdapter.openFile(`${person.id.substring(testRealmURL.length)}.json`);
1810
+ assert.ok(file, "the realm holds the saved card");
1811
+ });
1812
+ (0, import_qunit.test)("a save started in the same turn as a linked card's create does not send that card again", async function(assert) {
1813
+ let friend = new PersonDef({ name: "Friend" });
1814
+ await storeService.addWithoutPersisting(friend);
1815
+ let person = new PersonDef({ name: "Person" });
1816
+ person.bestFriend = friend;
1817
+ await storeService.addWithoutPersisting(person);
1818
+ let hold = holdCreateResponse(friend);
1819
+ let results;
1820
+ try {
1821
+ let creatingFriend = storeService.persistAndUpdate(friend);
1822
+ let savingPerson = storeService.persistAndUpdate(person);
1823
+ await hold.stored;
1824
+ hold.release();
1825
+ results = await Promise.all([creatingFriend, savingPerson]);
1826
+ } finally {
1827
+ hold.restore();
1828
+ }
1829
+ await settled();
1830
+ assert.true(results.every((r) => isCardInstance(r)), `both saves succeeded (resolved as: ${JSON.stringify(results)})`);
1831
+ assert.deepEqual(hold.writes.map((w) => includedLids(w.body)), [[], []], "neither request carried a card to create besides its own");
1832
+ });
1833
+ (0, import_qunit.test)("a save still creates a linked card that was never saved alongside it", async function(assert) {
1834
+ let friend = new PersonDef({ name: "Friend" });
1835
+ let person = new PersonDef({ name: "Person" });
1836
+ person.bestFriend = friend;
1837
+ await storeService.addWithoutPersisting(person);
1838
+ let hold = holdCreateResponse(friend);
1839
+ let personResult;
1840
+ try {
1841
+ personResult = await storeService.persistAndUpdate(person);
1842
+ } finally {
1843
+ hold.restore();
1844
+ }
1845
+ await settled();
1846
+ assert.true(isCardInstance(personResult), `the save succeeded (resolved as: ${JSON.stringify(personResult)})`);
1847
+ assert.deepEqual(hold.writes.map((w) => includedLids(w.body)), [[friend[localId]]], "one request carried the unsaved linked card as a card to create");
1848
+ let personFile = await testRealmAdapter.openFile(`${person.id.substring(testRealmURL.length)}.json`);
1849
+ let friendPath = JSON.parse(personFile.content).data.relationships.bestFriend.links.self;
1850
+ assert.ok(await testRealmAdapter.openFile(`${new URL(friendPath, person.id).href.substring(testRealmURL.length)}.json`), "the realm holds the linked card, created with the save");
1851
+ });
1852
+ (0, import_qunit.test)("a save waiting on a linked card whose create fails does not hang", async function(assert) {
1853
+ let friend = new PersonDef({ name: "Friend" });
1854
+ await storeService.addWithoutPersisting(friend);
1855
+ let person = new PersonDef({ name: "Person" });
1856
+ person.bestFriend = friend;
1857
+ await storeService.addWithoutPersisting(person);
1858
+ let hold = holdCreateResponse(friend, { fail: true });
1859
+ let friendResult;
1860
+ let personResult;
1861
+ try {
1862
+ let creatingFriend = storeService.persistAndUpdate(friend);
1863
+ await hold.stored;
1864
+ let savingPerson = storeService.persistAndUpdate(person);
1865
+ let personSettledWhileFriendHeld = await Promise.race([savingPerson.then(() => true), new Promise((r) => setTimeout(() => r(false), 500))]);
1866
+ assert.false(personSettledWhileFriendHeld, "the save waits while the linked card's create is unanswered");
1867
+ assert.deepEqual(hold.writes.map((w) => w.method), ["POST"], "nothing but the linked card's own create went out while it was unanswered");
1868
+ hold.release();
1869
+ [friendResult, personResult] = await Promise.all([creatingFriend, savingPerson]);
1870
+ } finally {
1871
+ hold.restore();
1872
+ }
1873
+ await settled();
1874
+ assert.false(isCardInstance(friendResult), "the linked card's create reported its failure");
1875
+ assert.true(isCardInstance(personResult), `the save answered, linked to the already-stored card (resolved as: ${JSON.stringify(personResult)})`);
1876
+ assert.deepEqual(includedLids(hold.writes.find((w) => w.body.data.lid === person[localId]).body), [friend[localId]], "with no create left on the wire, the save sent the linked card as a card to create");
1877
+ });
1878
+ (0, import_qunit.test)("loads FileDef links from included resources", async function(assert) {
1879
+ await testRealm.writeMany(new Map([
1880
+ ["gallery.gts", `
1881
+ import { CardDef, field, linksTo, linksToMany } from "@cardstack/base/card-api";
1882
+ import { FileDef } from "@cardstack/base/file-api";
1883
+
1884
+ export class Gallery extends CardDef {
1885
+ @field hero = linksTo(FileDef);
1886
+ @field attachments = linksToMany(FileDef);
1887
+ }
1888
+ `],
1889
+ ["Gallery/hero.json", JSON.stringify({
1890
+ data: {
1891
+ attributes: { cardInfo: {} },
1892
+ relationships: {
1893
+ hero: {
1894
+ links: { self: `${testRealmURL}hero.png` },
1895
+ data: {
1896
+ type: "file-meta",
1897
+ id: `${testRealmURL}hero.png`
1898
+ }
1899
+ },
1900
+ "attachments.0": {
1901
+ links: { self: `${testRealmURL}first.png` },
1902
+ data: {
1903
+ type: "file-meta",
1904
+ id: `${testRealmURL}first.png`
1905
+ }
1906
+ },
1907
+ "attachments.1": {
1908
+ links: { self: `${testRealmURL}second.png` },
1909
+ data: {
1910
+ type: "file-meta",
1911
+ id: `${testRealmURL}second.png`
1912
+ }
1913
+ }
1914
+ },
1915
+ meta: { adoptsFrom: {
1916
+ module: testRRI("gallery"),
1917
+ name: "Gallery"
1918
+ } }
1919
+ },
1920
+ included: [
1921
+ {
1922
+ type: "file-meta",
1923
+ id: `${testRealmURL}hero.png`,
1924
+ attributes: {
1925
+ name: "hero.png",
1926
+ url: `${testRealmURL}hero.png`,
1927
+ sourceUrl: `${testRealmURL}hero.png`,
1928
+ contentType: "image/png"
1929
+ },
1930
+ meta: { adoptsFrom: {
1931
+ module: "@cardstack/base/card-api",
1932
+ name: "FileDef"
1933
+ } }
1934
+ },
1935
+ {
1936
+ type: "file-meta",
1937
+ id: `${testRealmURL}first.png`,
1938
+ attributes: {
1939
+ name: "first.png",
1940
+ url: `${testRealmURL}first.png`,
1941
+ sourceUrl: `${testRealmURL}first.png`,
1942
+ contentType: "image/png"
1943
+ },
1944
+ meta: { adoptsFrom: {
1945
+ module: "@cardstack/base/card-api",
1946
+ name: "FileDef"
1947
+ } }
1948
+ },
1949
+ {
1950
+ type: "file-meta",
1951
+ id: `${testRealmURL}second.png`,
1952
+ attributes: {
1953
+ name: "second.png",
1954
+ url: `${testRealmURL}second.png`,
1955
+ sourceUrl: `${testRealmURL}second.png`,
1956
+ contentType: "image/png"
1957
+ },
1958
+ meta: { adoptsFrom: {
1959
+ module: "@cardstack/base/card-api",
1960
+ name: "FileDef"
1961
+ } }
1962
+ }
1963
+ ]
1964
+ })],
1965
+ ["hero.png", "mock hero image"],
1966
+ ["first.png", "mock first image"],
1967
+ ["second.png", "mock second image"]
1968
+ ]));
1969
+ let gallery = await storeService.get(`${testRealmURL}Gallery/hero`);
1970
+ assert.ok(gallery.hero, "hero is loaded from included resources");
1971
+ assert.strictEqual(gallery.hero?.id, `${testRealmURL}hero.png`, "hero FileDef has id set from file meta");
1972
+ assert.strictEqual(gallery.hero?.name, "hero.png", "hero FileDef uses file meta name");
1973
+ assert.strictEqual(gallery.hero?.url, `${testRealmURL}hero.png`, "hero FileDef uses file meta url");
1974
+ let attachments = gallery.attachments ?? [];
1975
+ assert.strictEqual(attachments.length, 2, "attachments are loaded from included resources");
1976
+ assert.strictEqual(attachments[0]?.id, `${testRealmURL}first.png`, "first attachment has id set from file meta");
1977
+ assert.strictEqual(attachments[0]?.name, "first.png", "first attachment uses file meta name");
1978
+ assert.strictEqual(attachments[1]?.id, `${testRealmURL}second.png`, "second attachment has id set from file meta");
1979
+ assert.strictEqual(attachments[1]?.name, "second.png", "second attachment uses file meta name");
1980
+ });
1981
+ (0, import_qunit.test)("uses cached FileDef for links.self when field expects FileDef", async function(assert) {
1982
+ await testRealm.writeMany(new Map([
1983
+ ["gallery.gts", `
1984
+ import { CardDef, field, linksTo } from "@cardstack/base/card-api";
1985
+ import { FileDef } from "@cardstack/base/file-api";
1986
+
1987
+ export class Gallery extends CardDef {
1988
+ @field hero = linksTo(FileDef);
1989
+ }
1990
+ `],
1991
+ ["Gallery/cached.json", JSON.stringify({ data: {
1992
+ attributes: { cardInfo: {} },
1993
+ relationships: { hero: {
1994
+ links: { self: `${testRealmURL}hero.png` },
1995
+ data: {
1996
+ type: "file-meta",
1997
+ id: `${testRealmURL}hero.png`
1998
+ }
1999
+ } },
2000
+ meta: { adoptsFrom: {
2001
+ module: testRRI("gallery"),
2002
+ name: "Gallery"
2003
+ } }
2004
+ } })],
2005
+ ["hero.png", "mock hero image"]
2006
+ ]));
2007
+ let cachedFile = await storeService.get(`${testRealmURL}hero.png`, { type: "file-meta" });
2008
+ let gallery = await storeService.get(`${testRealmURL}Gallery/cached`);
2009
+ assert.strictEqual(gallery.hero, cachedFile, "links.self resolves to cached FileDef for FileDef fields");
2010
+ });
2011
+ (0, import_qunit.test)("can skip waiting for the save when patching an instance", async function(assert) {
2012
+ assert.expect(4);
2013
+ let targetId = `${testRealmURL}Person/hassan`;
2014
+ let instance = await storeService.get(targetId);
2015
+ let didSave = false;
2016
+ this.onSave((url, doc) => {
2017
+ if (url.href === targetId) {
2018
+ didSave = true;
2019
+ assert.strictEqual(doc.data.attributes?.name, "Hassan Updated", "patched data is persisted");
2020
+ }
2021
+ });
2022
+ await storeService.patch(targetId, { attributes: { name: "Hassan Updated" } }, { doNotWaitForPersist: true });
2023
+ assert.strictEqual(instance.name, "Hassan Updated", "local instance updated immediately");
2024
+ assert.false(didSave, "instance has not been persisted yet");
2025
+ await waitUntil(() => didSave, { timeout: 1e4 });
2026
+ let file = await testRealmAdapter.openFile("Person/hassan.json");
2027
+ assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Hassan Updated", "remote document reflects patch after persistence completes");
2028
+ });
2029
+ (0, import_qunit.test)("can patch an unsaved instance", async function(assert) {
2030
+ let instance = new PersonDef({ name: "Andrea" });
2031
+ await storeService.addWithoutPersisting(instance, { realm: testRealmURL });
2032
+ await storeService.patch(instance[localId], {
2033
+ attributes: { name: "Andrea Updated" },
2034
+ relationships: {
2035
+ bestFriend: { links: { self: `${testRealmURL}Person/queenzy` } },
2036
+ "friends.0": { links: { self: `${testRealmURL}Person/germaine` } }
2037
+ }
2038
+ });
2039
+ let peekedInstance = storeService.peek(instance[localId]);
2040
+ let queenzy = storeService.peek(`${testRealmURL}Person/queenzy`);
2041
+ let germaine = storeService.peek(`${testRealmURL}Person/germaine`);
2042
+ assert.strictEqual(peekedInstance, instance, "the patched instance is in the store");
2043
+ assert.ok(isCardInstance(queenzy), "queenzy is in the store");
2044
+ assert.ok(isCardInstance(germaine), "germaine is in the store");
2045
+ assert.strictEqual(instance[realmURL]?.href, testRealmURL, "the realm config on the instance is preserved");
2046
+ assert.strictEqual(instance.name, "Andrea Updated", "the contains field was patched");
2047
+ assert.strictEqual(instance.bestFriend, queenzy, "the linksTo field was patched");
2048
+ assert.deepEqual(instance.friends, [germaine], "the linksToMany field was patched");
2049
+ await waitUntil(() => instance.id, { timeoutMessage: "waiting for instance to get assigned an id" });
2050
+ assert.ok(instance.id, "instance was assigned a remote id");
2051
+ });
2052
+ (0, import_qunit.test)("can skip save when patching an instance", async function(assert) {
2053
+ this.onSave(() => {
2054
+ assert.ok(false, "should not save");
2055
+ });
2056
+ let instance = await storeService.patch(`${testRealmURL}Person/hassan`, {
2057
+ attributes: { name: "Hassan Updated" },
2058
+ relationships: {
2059
+ bestFriend: { links: { self: `${testRealmURL}Person/jade` } },
2060
+ "friends.0": { links: { self: `${testRealmURL}Person/germaine` } }
2061
+ }
2062
+ }, { doNotPersist: true });
2063
+ let peekedInstance = storeService.peek(`${testRealmURL}Person/hassan`);
2064
+ let jade = storeService.peek(`${testRealmURL}Person/jade`);
2065
+ let germaine = storeService.peek(`${testRealmURL}Person/germaine`);
2066
+ assert.strictEqual(peekedInstance, instance, "the patched instance is in the store");
2067
+ assert.ok(isCardInstance(jade), "jade is in the store");
2068
+ assert.ok(isCardInstance(germaine), "germaine is in the store");
2069
+ assert.strictEqual(instance.name, "Hassan Updated", "the contains field was patched");
2070
+ assert.strictEqual(instance.bestFriend, jade, "the linksTo field was patched");
2071
+ assert.deepEqual(instance.friends, [germaine], "the linksToMany field was patched");
2072
+ });
2073
+ (0, import_qunit.test)("can search", async function(assert) {
2074
+ let results = await storeService.search({ filter: {
2075
+ on: {
2076
+ module: testRRI("person"),
2077
+ name: "Person"
2078
+ },
2079
+ eq: { name: "Hassan" }
2080
+ } }, [testRealmURL]);
2081
+ assert.strictEqual(results.length, 1, "the correct number of results are returned");
2082
+ assert.strictEqual(results[0].id, `${testRealmURL}Person/hassan`, "the result is correct");
2083
+ });
2084
+ function overrideSearchWith(doc) {
2085
+ registerRealmServerRoute({
2086
+ path: "/_federated-search",
2087
+ handler: async () => new Response(JSON.stringify(doc), {
2088
+ status: 200,
2089
+ headers: { "content-type": SupportedMimeType.CardJson }
2090
+ })
2091
+ });
2092
+ }
2093
+ function htmlOnlyEntryDoc(id, opts) {
2094
+ let htmlId = opts?.isFileMeta ? `${id}#fitted` : `${id}#fitted#${testRealmURL}person/Person`;
2095
+ return {
2096
+ data: [{
2097
+ type: "entry",
2098
+ id,
2099
+ relationships: { html: { data: [{
2100
+ type: "html",
2101
+ id: htmlId
2102
+ }] } }
2103
+ }],
2104
+ included: [{
2105
+ type: "html",
2106
+ id: htmlId,
2107
+ attributes: {
2108
+ html: "<div>prerendered</div>",
2109
+ cardType: "Person",
2110
+ format: "fitted"
2111
+ },
2112
+ relationships: { styles: { data: [] } }
2113
+ }],
2114
+ meta: { page: { total: 1 } }
2115
+ };
2116
+ }
2117
+ let personQuery = { filter: {
2118
+ on: {
2119
+ module: testRRI("person"),
2120
+ name: "Person"
2121
+ },
2122
+ eq: { name: "Hassan" }
2123
+ } };
2124
+ (0, import_qunit.test)("a search result with no item serialization is not deposited into the Store", async function(assert) {
2125
+ let id = `${testRealmURL}Person/html-only`;
2126
+ overrideSearchWith(htmlOnlyEntryDoc(id));
2127
+ try {
2128
+ let results = await storeService.search(personQuery, [testRealmURL]);
2129
+ assert.strictEqual(results.length, 0, "the html-only entry is not returned as a hydrated instance");
2130
+ assert.notOk(isCardInstance(storeService.peek(id)), "the html-only entry is not deposited in the Store");
2131
+ } finally {
2132
+ registerDefaultRoutes();
2133
+ }
2134
+ });
2135
+ (0, import_qunit.test)("a search result with no item serialization leaves a resident full instance untouched", async function(assert) {
2136
+ let id = `${testRealmURL}Person/hassan`;
2137
+ storeService.addReference(id);
2138
+ await storeService.flush();
2139
+ let before = storeService.peek(id);
2140
+ assert.true(isCardInstance(before), "the full instance is resident before the search");
2141
+ overrideSearchWith(htmlOnlyEntryDoc(id));
2142
+ try {
2143
+ let results = await storeService.search(personQuery, [testRealmURL]);
2144
+ assert.strictEqual(results.length, 0, "an entry with no serialization contributes no instance");
2145
+ let after = storeService.peek(id);
2146
+ assert.strictEqual(after, before, "the html-only entry left the resident full instance untouched");
2147
+ assert.true(isCardInstance(after), "still a full card instance");
2148
+ } finally {
2149
+ registerDefaultRoutes();
2150
+ }
2151
+ });
2152
+ (0, import_qunit.test)("a file-meta search result with no item serialization leaves a resident FileDef untouched", async function(assert) {
2153
+ await testRealm.write("hero.png", "mock hero image");
2154
+ let fileUrl = `${testRealmURL}hero.png`;
2155
+ let before = await storeService.get(fileUrl, { type: "file-meta" });
2156
+ storeService.addReference(fileUrl, { type: "file-meta" });
2157
+ assert.true(before?.constructor?.isFileDef, "the live FileDef is resident before the search");
2158
+ overrideSearchWith(htmlOnlyEntryDoc(fileUrl, { isFileMeta: true }));
2159
+ try {
2160
+ let results = await storeService.search(personQuery, [testRealmURL]);
2161
+ assert.strictEqual(results.length, 0, "an entry with no serialization contributes no instance");
2162
+ assert.true(storeService.peek(fileUrl, { type: "file-meta" })?.constructor?.isFileDef, "the resident live FileDef is untouched");
2163
+ assert.ok(Object.is(storeService.peek(fileUrl, { type: "file-meta" }), before), "still the same resident FileDef");
2164
+ } finally {
2165
+ storeService.dropReference(fileUrl);
2166
+ registerDefaultRoutes();
2167
+ }
2168
+ });
2169
+ (0, import_qunit.test)("an instance live updates from indexing events for an instance update", async function(assert) {
2170
+ assert.expect(2);
2171
+ let didSave = false;
2172
+ this.onSave(() => {
2173
+ didSave = true;
2174
+ });
2175
+ setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
2176
+ await renderComponent(class TestDriver extends Component {
2177
+ static {
2178
+ setComponentTemplate(templateFactory({
2179
+ "id": "ZD1xwmB+",
2180
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2181
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2182
+ "scope": () => [OperatorModeContainer, noop],
2183
+ "isStrictMode": true
2184
+ }), this);
2185
+ }
2186
+ });
2187
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
2188
+ attributes: { name: "Hassan updated" },
2189
+ meta: { adoptsFrom: {
2190
+ module: testRRI("person"),
2191
+ name: "Person"
2192
+ } }
2193
+ } }));
2194
+ await waitUntil(() => storeService.peek(`${testRealmURL}Person/hassan`)?.name === "Hassan updated");
2195
+ await storeService.flushSaves();
2196
+ assert.dom("[data-test-stack-card] [data-test-field=\"name\"]").containsText("Hassan updated", "card live updated");
2197
+ assert.false(didSave, "indexing updates do not auto save instances");
2198
+ });
2199
+ (0, import_qunit.test)("an instance live updates from indexing events for a code update", async function(assert) {
2200
+ setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
2201
+ await renderComponent(class TestDriver extends Component {
2202
+ static {
2203
+ setComponentTemplate(templateFactory({
2204
+ "id": "ZD1xwmB+",
2205
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2206
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2207
+ "scope": () => [OperatorModeContainer, noop],
2208
+ "isStrictMode": true
2209
+ }), this);
2210
+ }
2211
+ });
2212
+ let instance = await storeService.get(`${testRealmURL}Person/hassan`);
2213
+ await testRealm.write(`person.gts`, `
2214
+ import { contains, field, Component, CardDef, } from '@cardstack/base/card-api';
2215
+ import StringField from '@cardstack/base/string';
2216
+
2217
+ export class Person extends CardDef {
2218
+ @field name = contains(StringField);
2219
+ static isolated = class Isolated extends Component<typeof this> {
2220
+ <template>
2221
+ <div test-update>Hello</div>
2222
+ <@fields.firstName />
2223
+ </template>
2224
+ };
2225
+ }`.trim());
2226
+ await waitFor("[test-update]", { timeout: 5e3 });
2227
+ assert.dom("[test-update]").containsText("Hello", "the instance rendered with the new code");
2228
+ let newInstance = storeService.peek(`${testRealmURL}Person/hassan`);
2229
+ assert.notStrictEqual(instance[localId], newInstance[localId], "the updated instance is a different object than the original instance");
2230
+ });
2231
+ (0, import_qunit.test)("an instance live updates to a new type when its adoptsFrom changes", async function(assert) {
2232
+ setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
2233
+ await renderComponent(class TestDriver extends Component {
2234
+ static {
2235
+ setComponentTemplate(templateFactory({
2236
+ "id": "ZD1xwmB+",
2237
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2238
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2239
+ "scope": () => [OperatorModeContainer, noop],
2240
+ "isStrictMode": true
2241
+ }), this);
2242
+ }
2243
+ });
2244
+ let original = storeService.peek(`${testRealmURL}Person/hassan`);
2245
+ assert.true(original instanceof PersonDef, "the card starts out as a Person");
2246
+ assert.dom("[data-test-employee-badge]").doesNotExist();
2247
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
2248
+ attributes: { name: "Hassan" },
2249
+ meta: { adoptsFrom: {
2250
+ module: testRRI("employee"),
2251
+ name: "Employee"
2252
+ } }
2253
+ } }));
2254
+ await waitUntil(() => storeService.peek(`${testRealmURL}Person/hassan`) instanceof EmployeeDef, { timeout: 5e3 });
2255
+ let reloaded = storeService.peek(`${testRealmURL}Person/hassan`);
2256
+ assert.true(reloaded instanceof EmployeeDef, "the store now holds an Employee instance for the same id");
2257
+ await waitFor("[data-test-employee-badge]", { timeout: 5e3 });
2258
+ assert.dom("[data-test-employee-badge]").containsText("Employee: Hassan", "the card re-rendered using the new type");
2259
+ });
2260
+ (0, import_qunit.test)("an instance rebuilds when its adoptsFrom changes to an ancestor type", async function(assert) {
2261
+ await testRealm.write("Manager/m1.json", JSON.stringify({ data: {
2262
+ attributes: { name: "Hassan" },
2263
+ meta: { adoptsFrom: {
2264
+ module: testRRI("manager"),
2265
+ name: "Manager"
2266
+ } }
2267
+ } }));
2268
+ setCardInOperatorModeState(`${testRealmURL}Manager/m1`);
2269
+ await renderComponent(class TestDriver extends Component {
2270
+ static {
2271
+ setComponentTemplate(templateFactory({
2272
+ "id": "ZD1xwmB+",
2273
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2274
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2275
+ "scope": () => [OperatorModeContainer, noop],
2276
+ "isStrictMode": true
2277
+ }), this);
2278
+ }
2279
+ });
2280
+ await waitFor("[data-test-manager-badge]");
2281
+ let original = storeService.peek(`${testRealmURL}Manager/m1`);
2282
+ assert.true(original instanceof ManagerDef, "the card starts as a Manager");
2283
+ await testRealm.write("Manager/m1.json", JSON.stringify({ data: {
2284
+ attributes: { name: "Hassan" },
2285
+ meta: { adoptsFrom: {
2286
+ module: testRRI("employee"),
2287
+ name: "Employee"
2288
+ } }
2289
+ } }));
2290
+ await waitUntil(() => {
2291
+ let c = storeService.peek(`${testRealmURL}Manager/m1`);
2292
+ return c instanceof EmployeeDef && !(c instanceof ManagerDef);
2293
+ }, { timeout: 5e3 });
2294
+ await waitFor("[data-test-employee-badge]", { timeout: 5e3 });
2295
+ assert.dom("[data-test-employee-badge]").containsText("Employee: Hassan", "rebuilt as the ancestor type");
2296
+ assert.dom("[data-test-manager-badge]").doesNotExist("no longer rendered as the Manager subclass");
2297
+ });
2298
+ (0, import_qunit.test)("an instance can live update thru an error state", async function(assert) {
2299
+ setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
2300
+ await renderComponent(class TestDriver extends Component {
2301
+ static {
2302
+ setComponentTemplate(templateFactory({
2303
+ "id": "ZD1xwmB+",
2304
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2305
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2306
+ "scope": () => [OperatorModeContainer, noop],
2307
+ "isStrictMode": true
2308
+ }), this);
2309
+ }
2310
+ });
2311
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
2312
+ attributes: {
2313
+ name: "Hassan",
2314
+ hasError: true
2315
+ },
2316
+ meta: { adoptsFrom: {
2317
+ module: testRRI("person"),
2318
+ name: "Person"
2319
+ } }
2320
+ } }));
2321
+ await settled();
2322
+ assert.dom("[data-test-card-error]").exists("the card error is shown");
2323
+ assert.dom("[data-test-error-message]").containsText("intentional error thrown");
2324
+ await click("[data-test-toggle-details]");
2325
+ assert.dom("[data-test-error-details]").includesText("Stack trace: Error: Encountered error rendering HTML");
2326
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
2327
+ attributes: {
2328
+ name: "Hassan",
2329
+ hasError: false
2330
+ },
2331
+ meta: { adoptsFrom: {
2332
+ module: testRRI("person"),
2333
+ name: "Person"
2334
+ } }
2335
+ } }));
2336
+ await settled();
2337
+ assert.dom("[data-test-card-error]").doesNotExist("the error is dismissed");
2338
+ assert.dom("[data-test-stack-card] [data-test-field=\"name\"]").containsText("Hassan", "card is still rendered");
2339
+ });
2340
+ (0, import_qunit.test)("a card the realm holds but has not indexed yet shows as being prepared, then renders once indexing lands", async function(assert) {
2341
+ await testRealmAdapter.write("Person/pending.json", JSON.stringify({ data: {
2342
+ attributes: { name: "Pending" },
2343
+ meta: { adoptsFrom: {
2344
+ module: testRRI("person"),
2345
+ name: "Person"
2346
+ } }
2347
+ } }));
2348
+ setCardInOperatorModeState(`${testRealmURL}Person/pending`);
2349
+ await renderComponent(class TestDriver extends Component {
2350
+ static {
2351
+ setComponentTemplate(templateFactory({
2352
+ "id": "ZD1xwmB+",
2353
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2354
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2355
+ "scope": () => [OperatorModeContainer, noop],
2356
+ "isStrictMode": true
2357
+ }), this);
2358
+ }
2359
+ });
2360
+ await waitFor("[data-test-card-awaiting-index]");
2361
+ assert.dom("[data-test-card-awaiting-index]").containsText("Preparing this card", "the card reads as on its way rather than missing");
2362
+ assert.dom("[data-test-card-error]").doesNotExist("no card error is reported");
2363
+ await testRealm.write("Person/pending.json", JSON.stringify({ data: {
2364
+ attributes: { name: "Pending Person" },
2365
+ meta: { adoptsFrom: {
2366
+ module: testRRI("person"),
2367
+ name: "Person"
2368
+ } }
2369
+ } }));
2370
+ await settled();
2371
+ let id = `${testRealmURL}Person/pending`;
2372
+ if (document.querySelector("[data-test-card-awaiting-index]")) {
2373
+ let realmEvents = mockMatrixUtils.getRoomIds().flatMap((roomId) => mockMatrixUtils.getRoomEvents(roomId)).filter((event) => event.type === APP_BOXEL_REALM_EVENT_TYPE).sort((a, b) => a.origin_server_ts - b.origin_server_ts).slice(-5).map((event) => event.content);
2374
+ console.warn(`[awaiting-index-placeholder flake-probe] placeholder still shown after settled(). store error=${JSON.stringify(storeService.peekError(id) ?? null)}; store holds instance=${isCardInstance(storeService.peek(id))}; last realm events in mock homeserver=${JSON.stringify(realmEvents)}.`);
2375
+ }
2376
+ assert.dom("[data-test-card-awaiting-index]").doesNotExist("the placeholder is gone once the card is indexed");
2377
+ assert.dom(`[data-stack-card="${testRealmURL}Person/pending"] [data-test-field="name"]`).containsText("Pending Person", "the real card takes over once it is indexed");
2378
+ });
2379
+ (0, import_qunit.test)("an index event that lands while the first read is in flight still resolves the placeholder", async function(assert) {
2380
+ storeService.addReference(`${testRealmURL}Person/hassan`);
2381
+ await storeService.flush();
2382
+ await testRealmAdapter.write("Person/racing.json", JSON.stringify({ data: {
2383
+ attributes: { name: "Racing" },
2384
+ meta: { adoptsFrom: {
2385
+ module: testRRI("person"),
2386
+ name: "Person"
2387
+ } }
2388
+ } }));
2389
+ let cardService = getService("card-service");
2390
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
2391
+ let reached404 = new Deferred();
2392
+ let release404 = new Deferred();
2393
+ cardService.fetchJSON = async (url, args) => {
2394
+ if (!String(url).includes("Person/racing")) return originalFetchJSON(url, args);
2395
+ try {
2396
+ return await originalFetchJSON(url, args);
2397
+ } catch (err) {
2398
+ reached404.fulfill();
2399
+ await release404.promise;
2400
+ throw err;
2401
+ }
2402
+ };
2403
+ let messageService = getService("message-service");
2404
+ let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
2405
+ messageService.relayRealmEvent = () => {};
2406
+ try {
2407
+ let reading = storeService.get(`${testRealmURL}Person/racing`);
2408
+ await reached404.promise;
2409
+ await testRealm.write("Person/racing.json", JSON.stringify({ data: {
2410
+ attributes: { name: "Racing Person" },
2411
+ meta: { adoptsFrom: {
2412
+ module: testRRI("person"),
2413
+ name: "Person"
2414
+ } }
2415
+ } }));
2416
+ deliverRealmEvents({
2417
+ eventName: "index",
2418
+ indexType: "incremental",
2419
+ invalidations: [`${testRealmURL}Person/racing`],
2420
+ realmURL: testRealmURL
2421
+ });
2422
+ release404.fulfill();
2423
+ await reading;
2424
+ await settled();
2425
+ } finally {
2426
+ release404.fulfill();
2427
+ delete cardService.fetchJSON;
2428
+ messageService.relayRealmEvent = deliverRealmEvents;
2429
+ }
2430
+ let instance = storeService.peek(`${testRealmURL}Person/racing`);
2431
+ assert.true(isCardInstance(instance), "the store holds the card rather than the stale placeholder");
2432
+ assert.strictEqual(instance.name, "Racing Person", "and it is the indexed state");
2433
+ });
2434
+ (0, import_qunit.test)("a full reindex resolves a placeholder even though it names no cards", async function(assert) {
2435
+ storeService.addReference(`${testRealmURL}Person/hassan`);
2436
+ await storeService.flush();
2437
+ await testRealmAdapter.write("Person/swept.json", JSON.stringify({ data: {
2438
+ attributes: { name: "Swept" },
2439
+ meta: { adoptsFrom: {
2440
+ module: testRRI("person"),
2441
+ name: "Person"
2442
+ } }
2443
+ } }));
2444
+ let placeholder = await storeService.get(`${testRealmURL}Person/swept`);
2445
+ assert.true(placeholder.awaitingIndex, "the read leaves an awaiting-index placeholder");
2446
+ let messageService = getService("message-service");
2447
+ let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
2448
+ messageService.relayRealmEvent = () => {};
2449
+ try {
2450
+ await testRealm.write("Person/swept.json", JSON.stringify({ data: {
2451
+ attributes: { name: "Swept Person" },
2452
+ meta: { adoptsFrom: {
2453
+ module: testRRI("person"),
2454
+ name: "Person"
2455
+ } }
2456
+ } }));
2457
+ deliverRealmEvents({
2458
+ eventName: "index",
2459
+ indexType: "full",
2460
+ realmURL: testRealmURL
2461
+ });
2462
+ await settled();
2463
+ } finally {
2464
+ messageService.relayRealmEvent = deliverRealmEvents;
2465
+ }
2466
+ let instance = storeService.peek(`${testRealmURL}Person/swept`);
2467
+ assert.true(isCardInstance(instance), "the sweep replaced the placeholder with the card");
2468
+ assert.strictEqual(instance.name, "Swept Person", "and it is the indexed state");
2469
+ });
2470
+ (0, import_qunit.test)("a reload that 404s while the row is being rebuilt keeps the card instead of deleting it", async function(assert) {
2471
+ let url = `${testRealmURL}Person/rebuilt`;
2472
+ await testRealm.write("Person/rebuilt.json", JSON.stringify({ data: {
2473
+ attributes: { name: "Rebuilt" },
2474
+ meta: { adoptsFrom: {
2475
+ module: testRRI("person"),
2476
+ name: "Person"
2477
+ } }
2478
+ } }));
2479
+ storeService.addReference(url);
2480
+ await storeService.flush();
2481
+ assert.true(isCardInstance(storeService.peek(url)), "the card starts out loaded");
2482
+ let messageService = getService("message-service");
2483
+ let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
2484
+ messageService.relayRealmEvent = () => {};
2485
+ try {
2486
+ await testRealm.delete("Person/rebuilt.json");
2487
+ await testRealmAdapter.write("Person/rebuilt.json", JSON.stringify({ data: {
2488
+ attributes: { name: "Rebuilt" },
2489
+ meta: { adoptsFrom: {
2490
+ module: testRRI("person"),
2491
+ name: "Person"
2492
+ } }
2493
+ } }));
2494
+ deliverRealmEvents({
2495
+ eventName: "index",
2496
+ indexType: "incremental",
2497
+ invalidations: [url],
2498
+ realmURL: testRealmURL
2499
+ });
2500
+ await settled();
2501
+ } finally {
2502
+ messageService.relayRealmEvent = deliverRealmEvents;
2503
+ }
2504
+ assert.true(isCardInstance(storeService.peek(url)), "the card is still in the store — nothing was deleted");
2505
+ assert.strictEqual(storeService.peekError(url), void 0, "and it is left alone rather than covered by a placeholder");
2506
+ });
2507
+ (0, import_qunit.test)("a card already running in the store is never displaced by the awaiting-index placeholder", async function(assert) {
2508
+ let instance = await storeService.add(new PersonDef({ name: "Brand New" }));
2509
+ let url = instance.id;
2510
+ assert.ok(url, "the new card was assigned a remote id");
2511
+ let messageService = getService("message-service");
2512
+ let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
2513
+ messageService.relayRealmEvent = () => {};
2514
+ let cardService = getService("card-service");
2515
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
2516
+ cardService.fetchJSON = async (fetchUrl, args) => {
2517
+ if (String(fetchUrl).includes(url)) {
2518
+ let err = /* @__PURE__ */ new Error("awaiting index");
2519
+ err.status = 404;
2520
+ err.responseText = JSON.stringify({ errors: [{
2521
+ id: url,
2522
+ status: 404,
2523
+ title: "Not Found",
2524
+ message: `${url} has not finished indexing`,
2525
+ isCardError: true,
2526
+ awaitingIndex: true,
2527
+ additionalErrors: null
2528
+ }] });
2529
+ throw err;
2530
+ }
2531
+ return originalFetchJSON(fetchUrl, args);
2532
+ };
2533
+ try {
2534
+ deliverRealmEvents({
2535
+ eventName: "index",
2536
+ indexType: "incremental",
2537
+ invalidations: [url],
2538
+ realmURL: testRealmURL
2539
+ });
2540
+ await settled();
2541
+ } finally {
2542
+ delete cardService.fetchJSON;
2543
+ messageService.relayRealmEvent = deliverRealmEvents;
2544
+ }
2545
+ assert.strictEqual(storeService.peek(url), instance, "the running instance is still the one the store hands out");
2546
+ assert.strictEqual(storeService.peekError(url), void 0, "no placeholder stands in front of it");
2547
+ assert.ok(storeService.getSaveState(url), "and it is still autosaving, so the user can keep editing");
2548
+ });
2549
+ (0, import_qunit.test)("a full reindex resolves a placeholder whose read was still in flight when it landed", async function(assert) {
2550
+ storeService.addReference(`${testRealmURL}Person/hassan`);
2551
+ await storeService.flush();
2552
+ await testRealmAdapter.write("Person/swept-inflight.json", JSON.stringify({ data: {
2553
+ attributes: { name: "Swept In Flight" },
2554
+ meta: { adoptsFrom: {
2555
+ module: testRRI("person"),
2556
+ name: "Person"
2557
+ } }
2558
+ } }));
2559
+ let url = `${testRealmURL}Person/swept-inflight`;
2560
+ let cardService = getService("card-service");
2561
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
2562
+ let reached404 = new Deferred();
2563
+ let release404 = new Deferred();
2564
+ cardService.fetchJSON = async (fetchUrl, args) => {
2565
+ if (!String(fetchUrl).includes("Person/swept-inflight")) return originalFetchJSON(fetchUrl, args);
2566
+ try {
2567
+ return await originalFetchJSON(fetchUrl, args);
2568
+ } catch (err) {
2569
+ reached404.fulfill();
2570
+ await release404.promise;
2571
+ throw err;
2572
+ }
2573
+ };
2574
+ let messageService = getService("message-service");
2575
+ let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
2576
+ messageService.relayRealmEvent = () => {};
2577
+ try {
2578
+ let reading = storeService.get(url);
2579
+ await reached404.promise;
2580
+ await testRealm.write("Person/swept-inflight.json", JSON.stringify({ data: {
2581
+ attributes: { name: "Swept In Flight Person" },
2582
+ meta: { adoptsFrom: {
2583
+ module: testRRI("person"),
2584
+ name: "Person"
2585
+ } }
2586
+ } }));
2587
+ deliverRealmEvents({
2588
+ eventName: "index",
2589
+ indexType: "full",
2590
+ realmURL: testRealmURL
2591
+ });
2592
+ release404.fulfill();
2593
+ await reading;
2594
+ await settled();
2595
+ } finally {
2596
+ release404.fulfill();
2597
+ delete cardService.fetchJSON;
2598
+ messageService.relayRealmEvent = deliverRealmEvents;
2599
+ }
2600
+ let instance = storeService.peek(url);
2601
+ assert.true(isCardInstance(instance), "the card takes over rather than the placeholder being stranded");
2602
+ assert.strictEqual(instance.name, "Swept In Flight Person", "and it is the indexed state");
2603
+ });
2604
+ (0, import_qunit.test)("a duplicate incremental event does not reload a card the store already holds at that generation", async function(assert) {
2605
+ let url = `${testRealmURL}Person/echoed`;
2606
+ let events = interceptRealmEvents();
2607
+ let reads;
2608
+ try {
2609
+ await writePerson("Person/echoed.json", "Echoed");
2610
+ await events.nextEventFor(url);
2611
+ storeService.addReference(url);
2612
+ await storeService.flush();
2613
+ await writePerson("Person/echoed.json", "Echoed Again");
2614
+ let event = await events.nextEventFor(url);
2615
+ assert.strictEqual(typeof event.generation, "number", "the realm reported the generation its pass committed");
2616
+ let { versions: _versions, ...onGeneration } = event;
2617
+ reads = countCardReads("Person/echoed");
2618
+ events.deliver(onGeneration);
2619
+ await settled();
2620
+ assert.strictEqual(reads.count, 1, "the event is acted on once");
2621
+ assert.strictEqual(storeService.peek(url).name, "Echoed Again", "and the store holds what the pass wrote");
2622
+ events.deliver(onGeneration);
2623
+ await settled();
2624
+ assert.strictEqual(reads.count, 1, "the same event delivered a second time is a no-op");
2625
+ let { generation: _generation, ...withoutGeneration } = onGeneration;
2626
+ events.deliver(withoutGeneration);
2627
+ await settled();
2628
+ assert.strictEqual(reads.count, 2, "while an otherwise identical event carrying no generation does reload");
2629
+ } finally {
2630
+ reads?.stop();
2631
+ events.restore();
2632
+ }
2633
+ });
2634
+ (0, import_qunit.test)("a duplicate arriving while the first reload is still in flight is coalesced into it", async function(assert) {
2635
+ let url = `${testRealmURL}Person/coalesced`;
2636
+ let events = interceptRealmEvents();
2637
+ let reads;
2638
+ try {
2639
+ await writePerson("Person/coalesced.json", "Coalesced");
2640
+ await events.nextEventFor(url);
2641
+ storeService.addReference(url);
2642
+ await storeService.flush();
2643
+ await writePerson("Person/coalesced.json", "Coalesced Again");
2644
+ let event = await events.nextEventFor(url);
2645
+ reads = countCardReads("Person/coalesced");
2646
+ events.deliver(event);
2647
+ events.deliver(event);
2648
+ await settled();
2649
+ assert.strictEqual(reads.count, 1, "the duplicate is answered by the reload already in flight");
2650
+ assert.strictEqual(storeService.peek(url).name, "Coalesced Again", "and that reload still brought the state the pass wrote");
2651
+ let { generation: _generation, versions: _versions, ...bare } = event;
2652
+ events.deliver(bare);
2653
+ events.deliver(bare);
2654
+ await settled();
2655
+ assert.strictEqual(reads.count, 3, "while a pair carrying neither member reloads twice");
2656
+ } finally {
2657
+ reads?.stop();
2658
+ events.restore();
2659
+ }
2660
+ });
2661
+ (0, import_qunit.test)("an incremental event overtaken by a newer one does not reload", async function(assert) {
2662
+ let url = `${testRealmURL}Person/overtaken`;
2663
+ let events = interceptRealmEvents();
2664
+ let reads;
2665
+ try {
2666
+ await writePerson("Person/overtaken.json", "Overtaken");
2667
+ await events.nextEventFor(url);
2668
+ storeService.addReference(url);
2669
+ await storeService.flush();
2670
+ await writePerson("Person/overtaken.json", "Second");
2671
+ let earlier = await events.nextEventFor(url);
2672
+ await writePerson("Person/overtaken.json", "Third");
2673
+ let later = await events.nextEventFor(url);
2674
+ assert.true(later.generation > earlier.generation, "the two passes are ordered by generation");
2675
+ reads = countCardReads("Person/overtaken");
2676
+ events.deliver(later);
2677
+ await settled();
2678
+ assert.strictEqual(reads.count, 1, "the newer event is acted on");
2679
+ assert.strictEqual(storeService.peek(url).name, "Third", "and the store holds the state that pass wrote");
2680
+ events.deliver(earlier);
2681
+ await settled();
2682
+ assert.strictEqual(reads.count, 1, "the older event arriving after it is ignored");
2683
+ } finally {
2684
+ reads?.stop();
2685
+ events.restore();
2686
+ }
2687
+ });
2688
+ (0, import_qunit.test)("a write's echo is recognized by its version once the request id has aged out of this client's memory", async function(assert) {
2689
+ let url = `${testRealmURL}Person/aged-out`;
2690
+ let events = interceptRealmEvents();
2691
+ let reads;
2692
+ try {
2693
+ await writePerson("Person/aged-out.json", "Aged Out");
2694
+ await events.nextEventFor(url);
2695
+ storeService.addReference(url);
2696
+ await storeService.flush();
2697
+ let instance = storeService.peek(url);
2698
+ instance.name = "Aged Out Edit";
2699
+ storeService.save(url);
2700
+ await settled();
2701
+ let event = await events.nextEventFor(url);
2702
+ assert.true(event.generation > api.getCardMeta(instance, "generation"), "the event names a generation past the one the store holds");
2703
+ assert.strictEqual(api.getCardMeta(instance, "version"), event.versions?.[url], "and the store recorded the version its own write returned");
2704
+ let agedOut = {
2705
+ ...event,
2706
+ clientRequestId: "instance:aged-out-of-this-clients-memory"
2707
+ };
2708
+ reads = countCardReads("Person/aged-out");
2709
+ events.deliver(agedOut);
2710
+ await settled();
2711
+ assert.strictEqual(reads.count, 0, "the echo of our own write is not read back");
2712
+ assert.strictEqual(storeService.peek(url).name, "Aged Out Edit", "and the edit stands");
2713
+ let { versions: _versions, ...withoutVersions } = agedOut;
2714
+ events.deliver(withoutVersions);
2715
+ await settled();
2716
+ assert.strictEqual(reads.count, 1, "while the same event without the map does reload");
2717
+ } finally {
2718
+ reads?.stop();
2719
+ events.restore();
2720
+ }
2721
+ });
2722
+ (0, import_qunit.test)("a reload still in flight when the store is reset leaves the replacement identity map alone", async function(assert) {
2723
+ let url = `${testRealmURL}Person/reset-mid-reload`;
2724
+ let events = interceptRealmEvents();
2725
+ let cardService = getService("card-service");
2726
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
2727
+ let readHeld = new Deferred();
2728
+ let releaseRead = new Deferred();
2729
+ let holding = false;
2730
+ try {
2731
+ await writePerson("Person/reset-mid-reload.json", "Before Reset");
2732
+ await events.nextEventFor(url);
2733
+ storeService.addReference(url);
2734
+ await storeService.flush();
2735
+ let preReset = storeService.peek(url);
2736
+ await writePerson("Person/reset-mid-reload.json", "After Reset");
2737
+ let event = await events.nextEventFor(url);
2738
+ holding = true;
2739
+ cardService.fetchJSON = async (fetchUrl, args) => {
2740
+ if (holding && String(fetchUrl).includes("Person/reset-mid-reload") && (args?.method ?? "GET") === "GET") {
2741
+ holding = false;
2742
+ readHeld.fulfill();
2743
+ await releaseRead.promise;
2744
+ }
2745
+ return originalFetchJSON(fetchUrl, args);
2746
+ };
2747
+ events.deliver(event);
2748
+ await readHeld.promise;
2749
+ storeService.resetCache();
2750
+ let replacement = await storeService.get(url);
2751
+ assert.notStrictEqual(replacement[localId], preReset[localId], "the replacement identity map loads its own instance of the card");
2752
+ releaseRead.fulfill();
2753
+ await settled();
2754
+ assert.strictEqual(storeService.peek(url), replacement, "the resumed reload leaves the replacement instance in place");
2755
+ assert.strictEqual(storeService.peekError(url)?.message, void 0, "and records no error for the card");
2756
+ assert.strictEqual(replacement.name, "After Reset", "the replacement holds the state the realm wrote");
2757
+ } finally {
2758
+ releaseRead.fulfill();
2759
+ delete cardService.fetchJSON;
2760
+ events.restore();
2761
+ }
2762
+ });
2763
+ (0, import_qunit.test)("a reload still in flight when a code change resets identity in place leaves the re-established instance alone", async function(assert) {
2764
+ let url = `${testRealmURL}Person/code-change-mid-reload`;
2765
+ let events = interceptRealmEvents();
2766
+ let cardService = getService("card-service");
2767
+ let originalFetchJSON = cardService.fetchJSON.bind(cardService);
2768
+ let readHeld = new Deferred();
2769
+ let releaseRead = new Deferred();
2770
+ let holding = false;
2771
+ try {
2772
+ await writePerson("Person/code-change-mid-reload.json", "Before Reset");
2773
+ await events.nextEventFor(url);
2774
+ storeService.addReference(url);
2775
+ await storeService.flush();
2776
+ let preReset = storeService.peek(url);
2777
+ await writePerson("Person/code-change-mid-reload.json", "After Reset");
2778
+ let event = await events.nextEventFor(url);
2779
+ holding = true;
2780
+ cardService.fetchJSON = async (fetchUrl, args) => {
2781
+ if (holding && String(fetchUrl).includes("Person/code-change-mid-reload") && (args?.method ?? "GET") === "GET") {
2782
+ holding = false;
2783
+ readHeld.fulfill();
2784
+ await releaseRead.promise;
2785
+ }
2786
+ return originalFetchJSON(fetchUrl, args);
2787
+ };
2788
+ events.deliver(event);
2789
+ await readHeld.promise;
2790
+ storeService.refreshReferencesForCodeChange("test code change");
2791
+ let reestablished = await storeService.get(url);
2792
+ assert.strictEqual(storeService.peek(url), reestablished, "the store holds the instance the code change re-established");
2793
+ assert.notStrictEqual(reestablished[localId], preReset[localId], "the code change re-establishes the card as a fresh instance");
2794
+ releaseRead.fulfill();
2795
+ await settled();
2796
+ assert.strictEqual(storeService.peek(url), reestablished, "the resumed reload leaves the re-established instance in place");
2797
+ assert.strictEqual(storeService.peekError(url)?.message, void 0, "and records no error for the card");
2798
+ assert.strictEqual(reestablished.name, "After Reset", "the re-established instance holds the state the realm wrote");
2799
+ } finally {
2800
+ releaseRead.fulfill();
2801
+ delete cardService.fetchJSON;
2802
+ events.restore();
2803
+ }
2804
+ });
2805
+ async function holdIndexQueue() {
2806
+ let { queue } = getService("queue");
2807
+ let started = new Deferred();
2808
+ let release = new Deferred();
2809
+ queue.register("hold-index-queue", async () => {
2810
+ started.fulfill();
2811
+ await release.promise;
2812
+ return null;
2813
+ });
2814
+ let holder = await queue.publish({
2815
+ jobType: "hold-index-queue",
2816
+ concurrencyGroup: null,
2817
+ timeout: 30,
2818
+ args: null
2819
+ });
2820
+ await started.promise;
2821
+ let pendingCallers = () => queue.jobs.filter((job) => job.jobType === "incremental-index").flatMap((job) => (job.args?.coalescedCallers ?? []).map((caller) => caller.clientRequestId));
2822
+ let published = [];
2823
+ let arrivals = [];
2824
+ let heldAt = performance.now();
2825
+ let publish = queue.publish.bind(queue);
2826
+ queue.publish = async (args) => {
2827
+ let job = await publish(args);
2828
+ published.push({
2829
+ jobType: args.jobType,
2830
+ at: Math.round(performance.now() - heldAt)
2831
+ });
2832
+ for (let arrival of [...arrivals]) if (arrival.ready()) {
2833
+ arrivals.splice(arrivals.indexOf(arrival), 1);
2834
+ arrival.deferred.fulfill();
2835
+ }
2836
+ return job;
2837
+ };
2838
+ let callersArrive = async (description, ready) => {
2839
+ if (ready(pendingCallers())) return;
2840
+ let deferred = new Deferred();
2841
+ let arrival = {
2842
+ ready: () => ready(pendingCallers()),
2843
+ deferred
2844
+ };
2845
+ arrivals.push(arrival);
2846
+ let guard = setTimeout(() => {
2847
+ arrivals.splice(arrivals.indexOf(arrival), 1);
2848
+ deferred.reject(/* @__PURE__ */ new Error(`the held index pass never had ${description}: callers=${JSON.stringify(pendingCallers())} publishes=${JSON.stringify(published)}`));
2849
+ }, 2e4);
2850
+ try {
2851
+ await deferred.promise;
2852
+ } finally {
2853
+ clearTimeout(guard);
2854
+ }
2855
+ };
2856
+ return {
2857
+ holder,
2858
+ release,
2859
+ pendingCallers,
2860
+ callersArrive
2861
+ };
2862
+ }
2863
+ (0, import_qunit.test)("this client's own write, announced under another writer's id in a pass they shared, is not read back", async function(assert) {
2864
+ let mine = `${testRealmURL}Person/shared-mine`;
2865
+ let theirs = `${testRealmURL}Person/shared-theirs`;
2866
+ let events = interceptRealmEvents();
2867
+ let reads;
2868
+ let theirReads;
2869
+ let hold;
2870
+ try {
2871
+ await writePerson("Person/shared-mine.json", "Mine");
2872
+ await events.nextEventFor(mine);
2873
+ await writePerson("Person/shared-theirs.json", "Theirs");
2874
+ await events.nextEventFor(theirs);
2875
+ storeService.addReference(mine);
2876
+ storeService.addReference(theirs);
2877
+ await storeService.flush();
2878
+ hold = await holdIndexQueue();
2879
+ let theirWrite = testRealm.write("Person/shared-theirs.json", JSON.stringify({ data: {
2880
+ attributes: { name: "Theirs Edited" },
2881
+ meta: { adoptsFrom: {
2882
+ module: testRRI("person"),
2883
+ name: "Person"
2884
+ } }
2885
+ } }), { clientRequestId: "instance:another-tab" });
2886
+ await hold.callersArrive("the other writer's write", (callers) => callers.includes("instance:another-tab"));
2887
+ let instance = storeService.peek(mine);
2888
+ instance.name = "Mine Edited";
2889
+ let ownSave = storeService.save(mine);
2890
+ await hold.callersArrive("this client's save", (callers) => callers.length === 2);
2891
+ hold.release.fulfill();
2892
+ await Promise.all([
2893
+ theirWrite,
2894
+ ownSave,
2895
+ hold.holder.done
2896
+ ]);
2897
+ await settled();
2898
+ let event = await events.nextEventFor(mine);
2899
+ assert.strictEqual(event.clientRequestId, "instance:another-tab", "the pass is announced under the other writer's id");
2900
+ assert.deepEqual([...event.invalidations].sort(), [mine, theirs].sort(), "and it carries both writes");
2901
+ assert.strictEqual(event.coalescedWrites?.length, 2, "with both writers among its coalesced writes");
2902
+ reads = countCardReads("Person/shared-mine");
2903
+ theirReads = countCardReads("Person/shared-theirs");
2904
+ events.deliver(event);
2905
+ await settled();
2906
+ assert.strictEqual(reads.count, 0, "the card this client wrote is not read back");
2907
+ assert.strictEqual(storeService.peek(mine).name, "Mine Edited", "and its edit stands");
2908
+ assert.strictEqual(theirReads.count, 1, "while the card the other writer changed is");
2909
+ assert.strictEqual(storeService.peek(theirs).name, "Theirs Edited", "and the store holds what that writer wrote");
2910
+ let { coalescedWrites: _coalescedWrites, ...announcedAlone } = event;
2911
+ events.deliver(announcedAlone);
2912
+ await settled();
2913
+ assert.strictEqual(reads.count, 1, "while the same event without its coalesced writes reads it back");
2914
+ } finally {
2915
+ hold?.release.fulfill();
2916
+ reads?.stop();
2917
+ theirReads?.stop();
2918
+ events.restore();
2919
+ }
2920
+ });
2921
+ (0, import_qunit.test)("an instance can be restored after a loader reset", async function(assert) {
2922
+ setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
2923
+ await renderComponent(class TestDriver extends Component {
2924
+ static {
2925
+ setComponentTemplate(templateFactory({
2926
+ "id": "ZD1xwmB+",
2927
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2928
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2929
+ "scope": () => [OperatorModeContainer, noop],
2930
+ "isStrictMode": true
2931
+ }), this);
2932
+ }
2933
+ });
2934
+ assert.dom(`[data-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"]`).containsText("Hassan", "the card data is correct");
2935
+ await testRealm.write(`foo.gts`, `
2936
+ import { contains, CardDef } from '@cardstack/base/card-api';
2937
+ export class Foo extends CardDef {}
2938
+ `.trim());
2939
+ await waitFor("[data-test-stack-item-loading-card]", {
2940
+ count: 0,
2941
+ timeout: 5e3
2942
+ });
2943
+ assert.dom("[data-test-stack-item-loading-card]").doesNotExist("loading state is not displayed");
2944
+ assert.dom(`[data-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"]`).containsText("Hassan", "the card data is correct");
2945
+ });
2946
+ (0, import_qunit.test)("an instance that started out with a local ID can be restored after a loader reset", async function(assert) {
2947
+ let newInstance = new PersonDef({ name: "Andrea" });
2948
+ await storeService.add(newInstance, { realm: testRealmURL });
2949
+ setCardInOperatorModeState(newInstance[localId]);
2950
+ await renderComponent(class TestDriver extends Component {
2951
+ static {
2952
+ setComponentTemplate(templateFactory({
2953
+ "id": "ZD1xwmB+",
2954
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
2955
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
2956
+ "scope": () => [OperatorModeContainer, noop],
2957
+ "isStrictMode": true
2958
+ }), this);
2959
+ }
2960
+ });
2961
+ assert.dom(`[data-stack-card="${newInstance.id}"] [data-test-field="name"]`).containsText("Andrea", "the card data is correct");
2962
+ await testRealm.write(`foo.gts`, `
2963
+ import { contains, CardDef } from '@cardstack/base/card-api';
2964
+ export class Foo extends CardDef {}
2965
+ `.trim());
2966
+ await waitFor("[data-test-stack-item-loading-card]", {
2967
+ count: 0,
2968
+ timeout: 5e3
2969
+ });
2970
+ assert.dom("[data-test-stack-item-loading-card]").doesNotExist("loading state is not displayed");
2971
+ assert.dom(`[data-stack-card="${newInstance.id}"] [data-test-field="name"]`).containsText("Andrea", "the card data is correct");
2972
+ });
2973
+ (0, import_qunit.test)("an unsaved instance live updates when realm event matching local ID is received", async function(assert) {
2974
+ let newInstance = new PersonDef({ name: "Andrea" });
2975
+ await storeService.addWithoutPersisting(newInstance);
2976
+ storeService.addReference(`${testRealmURL}Person/hassan`);
2977
+ await storeService.flush();
2978
+ let instance = storeService.peek(`${testRealmURL}Person/hassan`);
2979
+ instance.friends = [newInstance];
2980
+ await waitUntil(() => newInstance.id, { timeout: 5e3 });
2981
+ assert.strictEqual(newInstance.id.split("/").pop(), newInstance[localId], "the new instance was live updated with a remote id");
2982
+ });
2983
+ (0, import_qunit.test)("an unsaved instance will auto save after it has been assigned a remote ID", async function(assert) {
2984
+ assert.expect(2);
2985
+ let newInstance = new PersonDef({ name: "Andrea" });
2986
+ await storeService.addWithoutPersisting(newInstance);
2987
+ storeService.addReference(`${testRealmURL}Person/hassan`);
2988
+ await storeService.flush();
2989
+ let instance = storeService.peek(`${testRealmURL}Person/hassan`);
2990
+ instance.friends = [newInstance];
2991
+ await waitUntil(() => newInstance.id, { timeout: 5e3 });
2992
+ this.onSave((url, doc) => {
2993
+ if (url.href === newInstance.id) {
2994
+ assert.strictEqual(url.href, newInstance.id, "the save url is correct");
2995
+ assert.strictEqual(doc.data.attributes?.name, "Air", "card data is correct");
2996
+ }
2997
+ });
2998
+ newInstance.name = "Air";
2999
+ });
3000
+ (0, import_qunit.test)("reference count is balanced when used with CardResource that is destroyed", async function(assert) {
3001
+ class Driver {
3002
+ static {
3003
+ decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
3004
+ return false;
3005
+ });
3006
+ }
3007
+ #showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
3008
+ static {
3009
+ decorateFieldV2(this.prototype, "id", [tracked]);
3010
+ }
3011
+ #id = (initializeDeferredDecorator(this, "id"), void 0);
3012
+ }
3013
+ let driver = new Driver();
3014
+ class ResourceConsumer extends Component {
3015
+ resource = getCard(this, () => driver.id);
3016
+ get renderedCard() {
3017
+ return this.resource.card?.constructor.getComponent(this.resource.card);
3018
+ }
3019
+ static {
3020
+ setComponentTemplate(templateFactory({
3021
+ "id": "XWrL4bCI",
3022
+ "block": "[[[41,[30,0,[\"resource\",\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"resource\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3023
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3024
+ "isStrictMode": true
3025
+ }), this);
3026
+ }
3027
+ }
3028
+ await renderComponent(class TestDriver extends Component {
3029
+ static {
3030
+ setComponentTemplate(templateFactory({
3031
+ "id": "hNRtWalG",
3032
+ "block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3033
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3034
+ "scope": () => [driver, ResourceConsumer],
3035
+ "isStrictMode": true
3036
+ }), this);
3037
+ }
3038
+ });
3039
+ driver.showComponent = true;
3040
+ let jade = `${testRealmURL}Person/jade`;
3041
+ let hassan = `${testRealmURL}Person/hassan`;
3042
+ driver.id = hassan;
3043
+ await settleCardRender(assert, hassan, `[data-test-rendered-card="${hassan}"]`);
3044
+ assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
3045
+ assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
3046
+ driver.id = jade;
3047
+ await settleCardRender(assert, jade, `[data-test-rendered-card="${jade}"]`);
3048
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3049
+ assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
3050
+ driver.showComponent = false;
3051
+ await waitFor(`[data-test-rendered-card]`, { count: 0 });
3052
+ assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
3053
+ assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
3054
+ });
3055
+ (0, import_qunit.test)("reference count is balanced when used with CardResource for file-meta that is destroyed", async function(assert) {
3056
+ class Driver {
3057
+ static {
3058
+ decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
3059
+ return false;
3060
+ });
3061
+ }
3062
+ #showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
3063
+ static {
3064
+ decorateFieldV2(this.prototype, "id", [tracked]);
3065
+ }
3066
+ #id = (initializeDeferredDecorator(this, "id"), void 0);
3067
+ }
3068
+ let driver = new Driver();
3069
+ let firstFile = `${testRealmURL}notes.txt`;
3070
+ let secondFile = `${testRealmURL}README.txt`;
3071
+ await testRealm.write("notes.txt", "notes");
3072
+ await testRealm.write("README.txt", "readme");
3073
+ class ResourceConsumer extends Component {
3074
+ resource = getCard(this, () => driver.id, { type: "file-meta" });
3075
+ static {
3076
+ setComponentTemplate(templateFactory({
3077
+ "id": "5jWS7tbo",
3078
+ "block": "[[[41,[30,0,[\"resource\",\"card\"]],[[[1,\" \"],[10,0],[15,\"data-test-rendered-file\",[30,0,[\"resource\",\"id\"]]],[12],[13],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3079
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3080
+ "isStrictMode": true
3081
+ }), this);
3082
+ }
3083
+ }
3084
+ await renderComponent(class TestDriver extends Component {
3085
+ static {
3086
+ setComponentTemplate(templateFactory({
3087
+ "id": "hNRtWalG",
3088
+ "block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3089
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3090
+ "scope": () => [driver, ResourceConsumer],
3091
+ "isStrictMode": true
3092
+ }), this);
3093
+ }
3094
+ });
3095
+ driver.showComponent = true;
3096
+ driver.id = firstFile;
3097
+ await settleCardRender(assert, firstFile, `[data-test-rendered-file="${firstFile}"]`, { type: "file-meta" });
3098
+ assert.strictEqual(storeService.getReferenceCount(firstFile), 1, `reference count for ${firstFile} is 1`);
3099
+ assert.strictEqual(storeService.getReferenceCount(secondFile), 0, `reference count for ${secondFile} is 0`);
3100
+ driver.id = secondFile;
3101
+ await settleCardRender(assert, secondFile, `[data-test-rendered-file="${secondFile}"]`, { type: "file-meta" });
3102
+ assert.strictEqual(storeService.getReferenceCount(firstFile), 0, `reference count for ${firstFile} is 0`);
3103
+ assert.strictEqual(storeService.getReferenceCount(secondFile), 1, `reference count for ${secondFile} is 1`);
3104
+ driver.showComponent = false;
3105
+ await waitFor(`[data-test-rendered-file]`, { count: 0 });
3106
+ assert.strictEqual(storeService.getReferenceCount(firstFile), 0, `reference count for ${firstFile} is 0`);
3107
+ assert.strictEqual(storeService.getReferenceCount(secondFile), 0, `reference count for ${secondFile} is 0`);
3108
+ });
3109
+ (0, import_qunit.test)("reference count is balanced during auto saving", async function(assert) {
3110
+ let hassan = `${testRealmURL}Person/hassan`;
3111
+ setCardInOperatorModeState(hassan, "edit");
3112
+ await renderComponent(class TestDriver extends Component {
3113
+ static {
3114
+ setComponentTemplate(templateFactory({
3115
+ "id": "ZD1xwmB+",
3116
+ "block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
3117
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3118
+ "scope": () => [OperatorModeContainer, noop],
3119
+ "isStrictMode": true
3120
+ }), this);
3121
+ }
3122
+ });
3123
+ assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
3124
+ await withSlowSave(1e3, async () => {
3125
+ await typeIn(`[data-test-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"] input`, " Paper");
3126
+ assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
3127
+ });
3128
+ assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
3129
+ });
3130
+ (0, import_qunit.test)("reference count is balanced when used with CardCollectionResource that is destroyed", async function(assert) {
3131
+ class Driver {
3132
+ static {
3133
+ decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
3134
+ return false;
3135
+ });
3136
+ }
3137
+ #showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
3138
+ static {
3139
+ decorateFieldV2(this.prototype, "id", [tracked]);
3140
+ }
3141
+ #id = (initializeDeferredDecorator(this, "id"), void 0);
3142
+ }
3143
+ let driver = new Driver();
3144
+ class ResourceConsumer extends Component {
3145
+ resource = getCardCollection(this, () => driver.id ? [driver.id] : []);
3146
+ get card() {
3147
+ return this.resource.cards[0];
3148
+ }
3149
+ get renderedCard() {
3150
+ return this.card?.constructor.getComponent(this.card);
3151
+ }
3152
+ static {
3153
+ setComponentTemplate(templateFactory({
3154
+ "id": "99aOV2w7",
3155
+ "block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3156
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3157
+ "isStrictMode": true
3158
+ }), this);
3159
+ }
3160
+ }
3161
+ await renderComponent(class TestDriver extends Component {
3162
+ static {
3163
+ setComponentTemplate(templateFactory({
3164
+ "id": "hNRtWalG",
3165
+ "block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3166
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3167
+ "scope": () => [driver, ResourceConsumer],
3168
+ "isStrictMode": true
3169
+ }), this);
3170
+ }
3171
+ });
3172
+ driver.showComponent = true;
3173
+ let jade = `${testRealmURL}Person/jade`;
3174
+ let hassan = `${testRealmURL}Person/hassan`;
3175
+ driver.id = hassan;
3176
+ await settleCardRender(assert, hassan, `[data-test-rendered-card="${hassan}"]`);
3177
+ assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
3178
+ assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
3179
+ driver.id = jade;
3180
+ await settleCardRender(assert, jade, `[data-test-rendered-card="${jade}"]`);
3181
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3182
+ assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
3183
+ driver.showComponent = false;
3184
+ await waitFor(`[data-test-rendered-card]`, { count: 0 });
3185
+ assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
3186
+ assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
3187
+ });
3188
+ (0, import_qunit.test)("reference count is balanced when used with SearchResource that is destroyed", async function(assert) {
3189
+ class Driver {
3190
+ static {
3191
+ decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
3192
+ return false;
3193
+ });
3194
+ }
3195
+ #showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
3196
+ static {
3197
+ decorateFieldV2(this.prototype, "id", [tracked]);
3198
+ }
3199
+ #id = (initializeDeferredDecorator(this, "id"), void 0);
3200
+ }
3201
+ let driver = new Driver();
3202
+ class ResourceConsumer extends Component {
3203
+ static {
3204
+ decorateFieldV2(this.prototype, "store", [service]);
3205
+ }
3206
+ #store = (initializeDeferredDecorator(this, "store"), void 0);
3207
+ get resource() {
3208
+ return this.store.getSearchResource(this, () => driver.id ? { filter: {
3209
+ on: baseCardRef,
3210
+ eq: { id: driver.id }
3211
+ } } : void 0);
3212
+ }
3213
+ static {
3214
+ decorateMethodV2(this.prototype, "resource", [cached]);
3215
+ }
3216
+ get card() {
3217
+ return this.resource.instances[0];
3218
+ }
3219
+ static {
3220
+ setComponentTemplate(templateFactory({
3221
+ "id": "F3i58yQO",
3222
+ "block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[10,0],[15,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]],[12],[1,\"\\n \"],[1,[30,0,[\"card\",\"id\"]]],[1,\"\\n \"],[13],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3223
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3224
+ "isStrictMode": true
3225
+ }), this);
3226
+ }
3227
+ }
3228
+ await renderComponent(class TestDriver extends Component {
3229
+ static {
3230
+ setComponentTemplate(templateFactory({
3231
+ "id": "hNRtWalG",
3232
+ "block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3233
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3234
+ "scope": () => [driver, ResourceConsumer],
3235
+ "isStrictMode": true
3236
+ }), this);
3237
+ }
3238
+ });
3239
+ driver.showComponent = true;
3240
+ let jade = `${testRealmURL}Person/jade`;
3241
+ let hassan = `${testRealmURL}Person/hassan`;
3242
+ driver.id = hassan;
3243
+ await waitUntil(() => storeService.getReferenceCount(hassan) === 1 && storeService.getReferenceCount(jade) === 0, { timeout: 1e4 });
3244
+ assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
3245
+ assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
3246
+ driver.id = jade;
3247
+ await waitUntil(() => storeService.getReferenceCount(jade) === 1 && storeService.getReferenceCount(hassan) === 0, { timeout: 1e4 });
3248
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3249
+ assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
3250
+ driver.showComponent = false;
3251
+ await waitUntil(() => storeService.getReferenceCount(jade) === 0 && storeService.getReferenceCount(hassan) === 0, { timeout: 1e4 });
3252
+ assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
3253
+ assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
3254
+ });
3255
+ (0, import_qunit.test)("reference count is balanced when used with SearchResource that live updates when there is a index event", async function(assert) {
3256
+ class Driver {
3257
+ static {
3258
+ decorateFieldV2(this.prototype, "id", [tracked]);
3259
+ }
3260
+ #id = (initializeDeferredDecorator(this, "id"), void 0);
3261
+ }
3262
+ let driver = new Driver();
3263
+ class ResourceConsumer extends Component {
3264
+ static {
3265
+ decorateFieldV2(this.prototype, "store", [service]);
3266
+ }
3267
+ #store = (initializeDeferredDecorator(this, "store"), void 0);
3268
+ get resource() {
3269
+ return this.store.getSearchResource(this, () => driver.id ? { filter: {
3270
+ on: baseCardRef,
3271
+ eq: { id: driver.id }
3272
+ } } : void 0, void 0, { isLive: true });
3273
+ }
3274
+ static {
3275
+ decorateMethodV2(this.prototype, "resource", [cached]);
3276
+ }
3277
+ get card() {
3278
+ return this.resource.instances[0];
3279
+ }
3280
+ get renderedCard() {
3281
+ return this.card?.constructor.getComponent(this.card);
3282
+ }
3283
+ static {
3284
+ setComponentTemplate(templateFactory({
3285
+ "id": "99aOV2w7",
3286
+ "block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3287
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3288
+ "isStrictMode": true
3289
+ }), this);
3290
+ }
3291
+ }
3292
+ await renderComponent(class TestDriver extends Component {
3293
+ static {
3294
+ setComponentTemplate(templateFactory({
3295
+ "id": "HtmuKyv7",
3296
+ "block": "[[[8,[32,0],null,null,null]],[],[]]",
3297
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3298
+ "scope": () => [ResourceConsumer],
3299
+ "isStrictMode": true
3300
+ }), this);
3301
+ }
3302
+ });
3303
+ let jade = `${testRealmURL}Person/jade`;
3304
+ driver.id = jade;
3305
+ await waitFor(`[data-test-rendered-card="${jade}"]`, { timeout: 5e3 });
3306
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3307
+ let deferred = new Deferred();
3308
+ let unsubscribe = getService("message-service").subscribe(testRealmURL, (ev) => {
3309
+ if (ev.eventName === "index" && ev.indexType === "incremental") {
3310
+ unsubscribe();
3311
+ deferred.fulfill();
3312
+ }
3313
+ });
3314
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
3315
+ attributes: { name: "Paper" },
3316
+ meta: { adoptsFrom: {
3317
+ module: testRRI("person"),
3318
+ name: "Person"
3319
+ } }
3320
+ } }));
3321
+ await deferred.promise;
3322
+ deferred = new Deferred();
3323
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
3324
+ attributes: { name: "Paper" },
3325
+ meta: { adoptsFrom: {
3326
+ module: testRRI("person"),
3327
+ name: "Person"
3328
+ } }
3329
+ } }));
3330
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3331
+ });
3332
+ (0, import_qunit.test)("reference count is balanced when used with CardCollectionResource when there is a index event", async function(assert) {
3333
+ class Driver {
3334
+ static {
3335
+ decorateFieldV2(this.prototype, "id", [tracked]);
3336
+ }
3337
+ #id = (initializeDeferredDecorator(this, "id"), void 0);
3338
+ }
3339
+ let driver = new Driver();
3340
+ class ResourceConsumer extends Component {
3341
+ resource = getCardCollection(this, () => driver.id ? [driver.id] : []);
3342
+ get card() {
3343
+ return this.resource.cards[0];
3344
+ }
3345
+ get renderedCard() {
3346
+ return this.card?.constructor.getComponent(this.card);
3347
+ }
3348
+ static {
3349
+ setComponentTemplate(templateFactory({
3350
+ "id": "99aOV2w7",
3351
+ "block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3352
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3353
+ "isStrictMode": true
3354
+ }), this);
3355
+ }
3356
+ }
3357
+ await renderComponent(class TestDriver extends Component {
3358
+ static {
3359
+ setComponentTemplate(templateFactory({
3360
+ "id": "HtmuKyv7",
3361
+ "block": "[[[8,[32,0],null,null,null]],[],[]]",
3362
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3363
+ "scope": () => [ResourceConsumer],
3364
+ "isStrictMode": true
3365
+ }), this);
3366
+ }
3367
+ });
3368
+ let jade = `${testRealmURL}Person/jade`;
3369
+ driver.id = jade;
3370
+ await waitFor(`[data-test-rendered-card="${jade}"]`, { timeout: 5e3 });
3371
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3372
+ let deferred = new Deferred();
3373
+ let unsubscribe = getService("message-service").subscribe(testRealmURL, (ev) => {
3374
+ if (ev.eventName === "index" && ev.indexType === "incremental") {
3375
+ unsubscribe();
3376
+ deferred.fulfill();
3377
+ }
3378
+ });
3379
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
3380
+ attributes: { name: "Paper" },
3381
+ meta: { adoptsFrom: {
3382
+ module: testRRI("person"),
3383
+ name: "Person"
3384
+ } }
3385
+ } }));
3386
+ await deferred.promise;
3387
+ deferred = new Deferred();
3388
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
3389
+ attributes: { name: "Paper" },
3390
+ meta: { adoptsFrom: {
3391
+ module: testRRI("person"),
3392
+ name: "Person"
3393
+ } }
3394
+ } }));
3395
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3396
+ });
3397
+ (0, import_qunit.test)("reference count is balanced when used with CardResource when there is a index event", async function(assert) {
3398
+ class Driver {
3399
+ static {
3400
+ decorateFieldV2(this.prototype, "id", [tracked]);
3401
+ }
3402
+ #id = (initializeDeferredDecorator(this, "id"), void 0);
3403
+ }
3404
+ let driver = new Driver();
3405
+ class ResourceConsumer extends Component {
3406
+ resource = getCard(this, () => driver.id);
3407
+ get renderedCard() {
3408
+ return this.resource.card?.constructor.getComponent(this.resource.card);
3409
+ }
3410
+ static {
3411
+ setComponentTemplate(templateFactory({
3412
+ "id": "XWrL4bCI",
3413
+ "block": "[[[41,[30,0,[\"resource\",\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"resource\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
3414
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3415
+ "isStrictMode": true
3416
+ }), this);
3417
+ }
3418
+ }
3419
+ await renderComponent(class TestDriver extends Component {
3420
+ static {
3421
+ setComponentTemplate(templateFactory({
3422
+ "id": "HtmuKyv7",
3423
+ "block": "[[[8,[32,0],null,null,null]],[],[]]",
3424
+ "moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
3425
+ "scope": () => [ResourceConsumer],
3426
+ "isStrictMode": true
3427
+ }), this);
3428
+ }
3429
+ });
3430
+ let jade = `${testRealmURL}Person/jade`;
3431
+ driver.id = jade;
3432
+ await waitFor(`[data-test-rendered-card="${jade}"]`, { timeout: 5e3 });
3433
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3434
+ let deferred = new Deferred();
3435
+ let unsubscribe = getService("message-service").subscribe(testRealmURL, (ev) => {
3436
+ if (ev.eventName === "index" && ev.indexType === "incremental") {
3437
+ unsubscribe();
3438
+ deferred.fulfill();
3439
+ }
3440
+ });
3441
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
3442
+ attributes: { name: "Paper" },
3443
+ meta: { adoptsFrom: {
3444
+ module: testRRI("person"),
3445
+ name: "Person"
3446
+ } }
3447
+ } }));
3448
+ await deferred.promise;
3449
+ deferred = new Deferred();
3450
+ await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
3451
+ attributes: { name: "Paper" },
3452
+ meta: { adoptsFrom: {
3453
+ module: testRRI("person"),
3454
+ name: "Person"
3455
+ } }
3456
+ } }));
3457
+ assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
3458
+ });
3459
+ });
3460
+ //#endregion