@harperfast/harper 5.2.5 → 5.2.7

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 (327) hide show
  1. package/bin/restart.ts +48 -23
  2. package/bin/restartExitWatchdog.ts +99 -0
  3. package/bin/run.ts +16 -10
  4. package/dist/bin/restart.js +39 -21
  5. package/dist/bin/restart.js.map +1 -1
  6. package/dist/bin/restartExitWatchdog.d.ts +5 -0
  7. package/dist/bin/restartExitWatchdog.js +100 -0
  8. package/dist/bin/restartExitWatchdog.js.map +1 -0
  9. package/dist/bin/run.d.ts +2 -0
  10. package/dist/bin/run.js +17 -10
  11. package/dist/bin/run.js.map +1 -1
  12. package/dist/resources/DatabaseTransaction.d.ts +18 -1
  13. package/dist/resources/DatabaseTransaction.js +63 -1
  14. package/dist/resources/DatabaseTransaction.js.map +1 -1
  15. package/dist/resources/LMDBTransaction.d.ts +2 -0
  16. package/dist/resources/LMDBTransaction.js +7 -1
  17. package/dist/resources/LMDBTransaction.js.map +1 -1
  18. package/dist/resources/PrimaryRocksDatabase.js +2 -3
  19. package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
  20. package/dist/resources/RecordEncoder.d.ts +16 -0
  21. package/dist/resources/RecordEncoder.js +93 -3
  22. package/dist/resources/RecordEncoder.js.map +1 -1
  23. package/dist/resources/Resource.js +5 -4
  24. package/dist/resources/Resource.js.map +1 -1
  25. package/dist/resources/ResourceInterface.d.ts +5 -0
  26. package/dist/resources/ResourceInterface.js.map +1 -1
  27. package/dist/resources/Table.js +106 -9
  28. package/dist/resources/Table.js.map +1 -1
  29. package/dist/resources/graphql.js +1 -1
  30. package/dist/resources/graphql.js.map +1 -1
  31. package/dist/resources/tracked.js +5 -0
  32. package/dist/resources/tracked.js.map +1 -1
  33. package/dist/resources/transaction.js +1 -1
  34. package/dist/resources/transaction.js.map +1 -1
  35. package/dist/server/threads/manageThreads.d.ts +1 -0
  36. package/dist/server/threads/manageThreads.js +20 -3
  37. package/dist/server/threads/manageThreads.js.map +1 -1
  38. package/dist/utility/processManagement/processManagement.js +21 -3
  39. package/dist/utility/processManagement/processManagement.js.map +1 -1
  40. package/npm-shrinkwrap.json +6 -6
  41. package/package.json +2 -2
  42. package/resources/DESIGN.md +24 -19
  43. package/resources/DatabaseTransaction.ts +63 -2
  44. package/resources/LMDBTransaction.ts +7 -1
  45. package/resources/PrimaryRocksDatabase.ts +3 -3
  46. package/resources/RecordEncoder.ts +85 -3
  47. package/resources/Resource.ts +6 -5
  48. package/resources/ResourceInterface.ts +5 -0
  49. package/resources/Table.ts +117 -9
  50. package/resources/graphql.ts +1 -1
  51. package/resources/tracked.ts +4 -0
  52. package/resources/transaction.ts +2 -2
  53. package/server/DESIGN.md +6 -0
  54. package/server/threads/manageThreads.js +17 -3
  55. package/studio/web/assets/{Chat-Lgj1d-8d.js → Chat-etJeJv4a.js} +71 -95
  56. package/studio/web/assets/FloatingChat-BvmHsuVo.js +23 -0
  57. package/studio/web/assets/abnfDiagram-VCTEODGH-C0_BAZyO.js +1 -0
  58. package/studio/web/assets/{alertDialog-BaBrZQ4M.js → alertDialog-DIHt7Z0r.js} +1 -1
  59. package/studio/web/assets/apiToken-Bl5LC8EH.js +1 -0
  60. package/studio/web/assets/applications-Dta6Y0Rg.js +296 -0
  61. package/studio/web/assets/arc-CVRByUzA.js +1 -0
  62. package/studio/web/assets/architecture-7GRP2DOG-DNdx5tEU.js +1 -0
  63. package/studio/web/assets/architectureDiagram-5GKGNRK7-BWzrASgm.js +36 -0
  64. package/studio/web/assets/authStore-qKmCZcaf.js +3 -0
  65. package/studio/web/assets/blockDiagram-NRAW4CY4-BdJX9Khj.js +129 -0
  66. package/studio/web/assets/{button-DfBmT4rc.js → button-DhiX-njv.js} +1 -1
  67. package/studio/web/assets/c4Diagram-UCG6FXSJ-CI6MzGmQ.js +38 -0
  68. package/studio/web/assets/channel-DtCV8PTL.js +1 -0
  69. package/studio/web/assets/chevron-up-Df2c8uoU.js +1 -0
  70. package/studio/web/assets/chunk-75Z2AOVW-BT8tVmks.js +2 -0
  71. package/studio/web/assets/chunk-DU6HZSFF-9kAOOmI6.js +127 -0
  72. package/studio/web/assets/{chunk-2GRJ4B5K-DtwG__pv.js → chunk-F27PBJKO-BW7ao8AY.js} +1 -1
  73. package/studio/web/assets/{chunk-KEIR6QF5-BICK3FdT.js → chunk-FOHPRMQF-DHwB1DNv.js} +2 -2
  74. package/studio/web/assets/{chunk-5RXB4S5H-D3c7okHC.js → chunk-G27WJ6UU-COyLMcgK.js} +2 -2
  75. package/studio/web/assets/chunk-GMAD6QVW-BNyXpoQO.js +72 -0
  76. package/studio/web/assets/chunk-JQ64N6SF-Cyz1IeLf.js +1 -0
  77. package/studio/web/assets/{chunk-GF5L2VYU-DreJ7Snz.js → chunk-LCL6LL3I-HOzK_ppE.js} +3 -3
  78. package/studio/web/assets/chunk-OBVCFTLP-D4wWOqDQ.js +1 -0
  79. package/studio/web/assets/chunk-P2QGCYS3-DmIFY4d7.js +1 -0
  80. package/studio/web/assets/{chunk-KBJHAD2P-CLDPbAA-.js → chunk-POPQ4Y6H-BPrvMyKz.js} +1 -1
  81. package/studio/web/assets/{chunk-4I5QYGJK-D1FhvtQq.js → chunk-PWAF6VOD-2zB6IW9i.js} +1 -1
  82. package/studio/web/assets/chunk-R7TYR2AO-Irip67yr.js +10 -0
  83. package/studio/web/assets/chunk-RHFEMEQ7-2FgyI8YU.js +168 -0
  84. package/studio/web/assets/{chunk-6Q2QTUOP-QviMM6bR.js → chunk-SVP7TREG-FwtbH2QC.js} +1 -1
  85. package/studio/web/assets/chunk-TEH6E4GO-P87k5mNi.js +62 -0
  86. package/studio/web/assets/{chunk-XXDRQBXY-CaP_jixK.js → chunk-XXDRQBXY-BoGZu3HH.js} +1 -1
  87. package/studio/web/assets/classDiagram-DTDB5LWJ-DbO_dCNE.js +1 -0
  88. package/studio/web/assets/classDiagram-v2-JRS7N3AN-DbO_dCNE.js +1 -0
  89. package/studio/web/assets/{cose-bilkent-JH36ORCC-BVTNhTKD.js → cose-bilkent-JH36ORCC-Cuuf67Bh.js} +1 -1
  90. package/studio/web/assets/{createLucideIcon-BMkDbMrz.js → createLucideIcon-BKGPfjm2.js} +1 -1
  91. package/studio/web/assets/cssMode-IAbO_2KK.js +1 -0
  92. package/studio/web/assets/cynefin-OW5HDTMX-BRkpLFQV.js +1 -0
  93. package/studio/web/assets/cynefinDiagram-5FMLGOSQ-CHT1DaX6.js +62 -0
  94. package/studio/web/assets/cytoscape.esm-C2x7inlt.js +321 -0
  95. package/studio/web/assets/dagre-3AP2YEHR-DpUXBh63.js +4 -0
  96. package/studio/web/assets/dagre-PrKaheQc.js +1 -0
  97. package/studio/web/assets/diagram-S7CK7UJ4-BuymVFZT.js +30 -0
  98. package/studio/web/assets/diagram-UQ7AKVKN-CyP148RM.js +41 -0
  99. package/studio/web/assets/diagram-VSXAHHWV-CoCAg3M9.js +3 -0
  100. package/studio/web/assets/diagram-VX7I27RA-BpOqCFca.js +24 -0
  101. package/studio/web/assets/diagram-Z3DM3KII-Bfpw7Vbj.js +24 -0
  102. package/studio/web/assets/dialog-CBf0Mr1d.js +1 -0
  103. package/studio/web/assets/{dist-CeoU7cfW.js → dist-kYfyPZP9.js} +1 -1
  104. package/studio/web/assets/{dist-cY0BPcz0.js → dist-lkA3O3eM.js} +1 -1
  105. package/studio/web/assets/download-BtTOBem-.js +1 -0
  106. package/studio/web/assets/ebnfDiagram-PWID7BFC-DS_6aWqL.js +1 -0
  107. package/studio/web/assets/editor-CeRXEhRl.js +1 -0
  108. package/studio/web/assets/erDiagram-SSCWMZ5O-DJNk6Fgw.js +99 -0
  109. package/studio/web/assets/eventmodeling-NTZA5JFV-5jbe4A5P.js +1 -0
  110. package/studio/web/assets/flowDiagram-A5DVABFB-Dp9Ezlow.js +1 -0
  111. package/studio/web/assets/{ganttDiagram-PKOTCBZU-Cit41Zp3.js → ganttDiagram-EL5Y4UJY-2pOExxMY.js} +2 -2
  112. package/studio/web/assets/{getAnalytics-rTxZLIM5.js → getAnalytics-D4LKGeVy.js} +1 -1
  113. package/studio/web/assets/gitGraph-4MIJSDKK-CH5ZxwzF.js +1 -0
  114. package/studio/web/assets/gitGraphDiagram-WWUBYQGX-DVIsIhbO.js +106 -0
  115. package/studio/web/assets/html-DOV4s_YT.js +1 -0
  116. package/studio/web/assets/htmlMode-CdqjnAh4.js +1 -0
  117. package/studio/web/assets/index-CTqasm6g.js +824 -0
  118. package/studio/web/assets/index-Cxj2_wsl.css +1 -0
  119. package/studio/web/assets/index.lazy-VmcKgiEy.js +2 -0
  120. package/studio/web/assets/info-A6RAGUB7-CPQfTnaG.js +1 -0
  121. package/studio/web/assets/infoDiagram-RXCK75RN-DlwLYlwm.js +2 -0
  122. package/studio/web/assets/{ishikawaDiagram-WSZJBQD7-BJYRB-hU.js → ishikawaDiagram-5VMMS53U-BRXRp29U.js} +2 -2
  123. package/studio/web/assets/{javascript-CGzSV8Sd.js → javascript-Dj7yXfx5.js} +1 -1
  124. package/studio/web/assets/{journeyDiagram-NVQOT4AX-B8K4wuMz.js → journeyDiagram-EYS64GPL-B0ou8k0n.js} +1 -1
  125. package/studio/web/assets/jsonMode-khk65qzx.js +1 -0
  126. package/studio/web/assets/{kanban-definition-27J2QSJJ-DKFV1ovM.js → kanban-definition-3QL26DDD-uYg7iYzp.js} +11 -11
  127. package/studio/web/assets/languageServices-D_06p7dw.js +1 -0
  128. package/studio/web/assets/linear-Cnt8506Q.js +1 -0
  129. package/studio/web/assets/lspLanguageFeatures-DTA6wyQw.js +4 -0
  130. package/studio/web/assets/mermaid-parser.core-Ck-fC8b7.js +7 -0
  131. package/studio/web/assets/mermaid.core-CP8aNNYm.js +44 -0
  132. package/studio/web/assets/{mindmap-definition-FAOFIHXS-CKL4PdAv.js → mindmap-definition-FBJOCRG2-CgTZ-rit.js} +25 -25
  133. package/studio/web/assets/notifications-Bah46LXX.js +1 -0
  134. package/studio/web/assets/notifications-CBZXgxVc.js +1 -0
  135. package/studio/web/assets/packet-AYTQ26CC-DEyoPtPb.js +1 -0
  136. package/studio/web/assets/pegDiagram-XKGWAZYB-DrD-7sD9.js +1 -0
  137. package/studio/web/assets/pie-WAS4IAKB-wjj-EI1d.js +1 -0
  138. package/studio/web/assets/pieDiagram-E7YTZNPT-GntqDCzv.js +39 -0
  139. package/studio/web/assets/profile-QspOun_j.js +1 -0
  140. package/studio/web/assets/{quadrantDiagram-CIZ2JOQS-CSbsuWtH.js → quadrantDiagram-AXDQQJYC-0UeqXQGd.js} +1 -1
  141. package/studio/web/assets/radar-RG4KPBEZ-DFSA5h7k.js +1 -0
  142. package/studio/web/assets/railroad-74A4TZTK-CaOUG9wR.js +1 -0
  143. package/studio/web/assets/railroad-abnf-HS5TGJTU-Bc0Qi0WH.js +1 -0
  144. package/studio/web/assets/railroad-ebnf-LZEXJU2U-G8rVVZ2C.js +1 -0
  145. package/studio/web/assets/railroad-peg-WCYAUIDC-CrehKBhC.js +1 -0
  146. package/studio/web/assets/railroadDiagram-O6MQD6OU-yHUELZaV.js +1 -0
  147. package/studio/web/assets/regions-QdUi7bQ9.js +1 -0
  148. package/studio/web/assets/{editor.api-eUd8PqEu.js → register-Buvoxmb8.js} +139 -138
  149. package/studio/web/assets/{requirementDiagram-LRYGKXZP-ZIF0Wlho.js → requirementDiagram-EFPCY7ZU-DNEGFjuW.js} +2 -2
  150. package/studio/web/assets/rolldown-runtime-hePW80VL.js +1 -0
  151. package/studio/web/assets/safeParse-DeaoCCWH.js +1 -0
  152. package/studio/web/assets/{sankeyDiagram-W5VNT64P-BcRESt9x.js → sankeyDiagram-P5KCCOFB-DpyAmSVR.js} +1 -1
  153. package/studio/web/assets/{sequenceDiagram-SI44F4Z6-OpgTeJNU.js → sequenceDiagram-WJ2MYXX4-TyaT7xNk.js} +1 -1
  154. package/studio/web/assets/setComponentFile-BI4E_iDe.js +1 -0
  155. package/studio/web/assets/setLocalStorage-D_kflv4U.js +1 -0
  156. package/studio/web/assets/setSessionStorage-B0bf71m4.js +1 -0
  157. package/studio/web/assets/setup-Cop6LBQN.js +2 -0
  158. package/studio/web/assets/src-CMc7m_Ut.js +1 -0
  159. package/studio/web/assets/stateDiagram-HBIQ2CUA-CeEdTArZ.js +1 -0
  160. package/studio/web/assets/stateDiagram-v2-4QOOHH4V-D4tuw9Su.js +1 -0
  161. package/studio/web/assets/status-DRu3zRgl.js +61 -0
  162. package/studio/web/assets/step-vX8bovaY.js +1 -0
  163. package/studio/web/assets/swimlanes-XN3QIQJK-B54FmF46.js +1 -0
  164. package/studio/web/assets/swimlanesDiagram-VK2B7HYN-XOhmNEvq.js +8 -0
  165. package/studio/web/assets/tabs-B_G5zscN.js +1 -0
  166. package/studio/web/assets/{time-D55sDum-.js → time-Cclkb7kQ.js} +1 -1
  167. package/studio/web/assets/{timeline-definition-Z64GVDOM-Dy5A_tK2.js → timeline-definition-24CTP7MA-D-a9ujbo.js} +5 -5
  168. package/studio/web/assets/toggleHighContrast-C0dJLmZ0.js +49 -0
  169. package/studio/web/assets/treeView-Q6P3EWNA-CrW_6JnS.js +1 -0
  170. package/studio/web/assets/treemap-WGGIJYW6-BxyYLdP_.js +1 -0
  171. package/studio/web/assets/tsMode-dbDiapTA.js +11 -0
  172. package/studio/web/assets/typescript-CT1826cL.js +1 -0
  173. package/studio/web/assets/useEntityRestURL-D1u1X_gE.js +1 -0
  174. package/studio/web/assets/useLocalStorage-Dtj1QS8_.js +1 -0
  175. package/studio/web/assets/{vendor-core-CddkYGh5.js → vendor-core-RCcadM3e.js} +1 -1
  176. package/studio/web/assets/vendor-datadog-BRv-mOv1.js +6 -0
  177. package/studio/web/assets/{vendor-react-BhazFIp8.js → vendor-react-Dyj4O3HE.js} +1 -1
  178. package/studio/web/assets/vendor-tanstack-BiFWSB3W.js +1 -0
  179. package/studio/web/assets/{vendor-ui-BLIveqaL.js → vendor-ui-vhu-UHhF.js} +11 -11
  180. package/studio/web/assets/{vennDiagram-T6HMQDX7-DRvMIiSo.js → vennDiagram-4TSXK5OY-Cy7s7Mpy.js} +3 -3
  181. package/studio/web/assets/wardley-WFR3VGLG-BeBL35g2.js +1 -0
  182. package/studio/web/assets/{wardleyDiagram-T6FBY63Y-B04FSA0i.js → wardleyDiagram-VM6X3IG4-BylmIGSg.js} +3 -3
  183. package/studio/web/assets/workers-FpR9_D2K.js +3 -0
  184. package/studio/web/assets/x-B9o9hsep.js +1 -0
  185. package/studio/web/assets/xml-ZjKUMjth.js +1 -0
  186. package/studio/web/assets/{xychartDiagram-ELKLHX3M-BE0X7RA7.js → xychartDiagram-S5SC5T6Z-CoKALMXr.js} +3 -3
  187. package/studio/web/assets/yaml-B6gXbZU6.js +1 -0
  188. package/studio/web/assets/{yaml.worker-Iyy2Pf1T.js → yaml.worker-BDL8_iuk.js} +153 -153
  189. package/studio/web/harper-studio_black.png +0 -0
  190. package/studio/web/index.html +18 -24
  191. package/utility/processManagement/processManagement.js +19 -3
  192. package/studio/web/assets/FloatingChat-jLWvR4kI.js +0 -23
  193. package/studio/web/assets/abnfDiagram-N423BO3Z-BRuH0ywn.js +0 -1
  194. package/studio/web/assets/apiToken-DYI4DqWa.js +0 -1
  195. package/studio/web/assets/applications-DCmc9-lk.js +0 -296
  196. package/studio/web/assets/arc-3Xw6uabx.js +0 -1
  197. package/studio/web/assets/architecture-TIHT7OUA-CsHfPErM.js +0 -1
  198. package/studio/web/assets/architectureDiagram-T3A2C74G-DrwbS7Gp.js +0 -36
  199. package/studio/web/assets/array-BifhSqXX.js +0 -1
  200. package/studio/web/assets/authStore-B3IhXrn6.js +0 -3
  201. package/studio/web/assets/blockDiagram-VBNYF7ZC-DKN1mht5.js +0 -132
  202. package/studio/web/assets/c4Diagram-5PPSVZJV-CT9bmjm_.js +0 -10
  203. package/studio/web/assets/card-ByrPS_wa.js +0 -1
  204. package/studio/web/assets/channel-mnKBfsP-.js +0 -1
  205. package/studio/web/assets/chevron-right-CY-tr2sG.js +0 -1
  206. package/studio/web/assets/chunk-3NCLNEKW-BVj72ixc.js +0 -1
  207. package/studio/web/assets/chunk-5FCAYU7R-Dh5nylU8.js +0 -1
  208. package/studio/web/assets/chunk-5HE753X5-Bw-yg4kO.js +0 -1
  209. package/studio/web/assets/chunk-5JV3BV7I-Cy5pj3QY.js +0 -1
  210. package/studio/web/assets/chunk-5TONJI2A-DQOY3q1H.js +0 -2
  211. package/studio/web/assets/chunk-7BUUIJ7U-Bb538aSH.js +0 -1
  212. package/studio/web/assets/chunk-7Z6QIM7H-BJhESwQK.js +0 -10
  213. package/studio/web/assets/chunk-BIQX33UG-DZEsGuSn.js +0 -1
  214. package/studio/web/assets/chunk-CQNSW5MT-B8S09OIh.js +0 -1
  215. package/studio/web/assets/chunk-CYSBUYHQ-C1Rf4art.js +0 -1
  216. package/studio/web/assets/chunk-EMLP6XTP-RLD4nXpI.js +0 -1
  217. package/studio/web/assets/chunk-I66GZJ75-DHPYnKNr.js +0 -125
  218. package/studio/web/assets/chunk-J7OUQ5F2-DcY_kb6i.js +0 -2
  219. package/studio/web/assets/chunk-JG7HCLWE-BYfiSaVt.js +0 -2
  220. package/studio/web/assets/chunk-JQJVKLGR-DtEmbHZj.js +0 -156
  221. package/studio/web/assets/chunk-MOZMSUNE-XVucA-n6.js +0 -1
  222. package/studio/web/assets/chunk-NSK5VX7P-DDFNzCU_.js +0 -2
  223. package/studio/web/assets/chunk-OSBZ3O6U-CrKZOUOr.js +0 -1
  224. package/studio/web/assets/chunk-QBLGF6JB-CxAyS2mW.js +0 -1
  225. package/studio/web/assets/chunk-QR6OTTB3-Df7OCENk.js +0 -62
  226. package/studio/web/assets/chunk-R7FJI6CG-Cnn3gE-Y.js +0 -1
  227. package/studio/web/assets/chunk-RYQCIY6F-N0MDKk5G.js +0 -1
  228. package/studio/web/assets/chunk-U6XO7XAA-BFxjP5U3.js +0 -2
  229. package/studio/web/assets/chunk-UBXNYLIW-rn0yw1mp.js +0 -1
  230. package/studio/web/assets/chunk-W5SLKNZC-DKMlAWZk.js +0 -1
  231. package/studio/web/assets/chunk-WRU74C26-Dg10j8Pf.js +0 -70
  232. package/studio/web/assets/chunk-YOTPTUD7-D0vRKqYp.js +0 -1
  233. package/studio/web/assets/chunk-ZIRB5QZD-O39ZBUk3.js +0 -32
  234. package/studio/web/assets/classDiagram-JCYQIIEL-BrXNP4fl.js +0 -1
  235. package/studio/web/assets/classDiagram-v2-OCEON4UE-BrXNP4fl.js +0 -1
  236. package/studio/web/assets/cssMode-DipmMR_-.js +0 -1
  237. package/studio/web/assets/cynefin-VYW2F7L2-Ds2Fw2Y0.js +0 -1
  238. package/studio/web/assets/cynefinDiagram-MW4NZA55-DcTzrsC5.js +0 -62
  239. package/studio/web/assets/cytoscape.esm-B-NFISlW.js +0 -321
  240. package/studio/web/assets/dagre-Buvkdvvj.js +0 -1
  241. package/studio/web/assets/dagre-VZM6K2ZE-CMyJ9QPU.js +0 -4
  242. package/studio/web/assets/diagram-7IWD3JNH-jEGuzdp3.js +0 -30
  243. package/studio/web/assets/diagram-B4RE2ZJO-Ba7wC7iw.js +0 -3
  244. package/studio/web/assets/diagram-LBJQPF4R-Bm7Wj_dF.js +0 -24
  245. package/studio/web/assets/diagram-Q27KOJAE-C-gdktLC.js +0 -24
  246. package/studio/web/assets/diagram-UB23O5K3-COBVIEEk.js +0 -41
  247. package/studio/web/assets/ebnfDiagram-BXEA7PRR-G-t56mVV.js +0 -1
  248. package/studio/web/assets/editor-BDfNodZS.js +0 -1
  249. package/studio/web/assets/erDiagram-JOGREHBK-DpHzpqx1.js +0 -85
  250. package/studio/web/assets/eventmodeling-45OFAUF4-CLEiVx5s.js +0 -1
  251. package/studio/web/assets/flowDiagram-UKHOOZJN-CIxxUUxn.js +0 -1
  252. package/studio/web/assets/getRegistrationInfo--NLLrics.js +0 -1
  253. package/studio/web/assets/gitGraph-TEB2WS4Q-CZFBqwW-.js +0 -1
  254. package/studio/web/assets/gitGraphDiagram-DS77QQ5N-DuGnRv2R.js +0 -106
  255. package/studio/web/assets/html-DmSSmgE8.js +0 -1
  256. package/studio/web/assets/htmlMode-B2LqJw1z.js +0 -1
  257. package/studio/web/assets/index-BO3NaEw8.css +0 -1
  258. package/studio/web/assets/index-BnYZFLIB.css +0 -1
  259. package/studio/web/assets/index-CqbCnqsT.js +0 -810
  260. package/studio/web/assets/index.lazy-BNqr3j0f.js +0 -13
  261. package/studio/web/assets/info-DKCQHKI2--1InqQeT.js +0 -1
  262. package/studio/web/assets/infoDiagram-6WML65LV-DliK38kp.js +0 -2
  263. package/studio/web/assets/isArrayLikeObject-BHDnhloL.js +0 -1
  264. package/studio/web/assets/jsonMode-BVS6P5Xk.js +0 -1
  265. package/studio/web/assets/languageServices-Bl-BvoAb.js +0 -1
  266. package/studio/web/assets/line-Bom3IjHi.js +0 -1
  267. package/studio/web/assets/linear-DwB_ruUT.js +0 -1
  268. package/studio/web/assets/lspLanguageFeatures-C7XtZA_w.js +0 -4
  269. package/studio/web/assets/map-BaFkSB1l.js +0 -1
  270. package/studio/web/assets/math-Bi_r_ZWc.js +0 -1
  271. package/studio/web/assets/mermaid-parser.core-Dd4RYr9Q.js +0 -4
  272. package/studio/web/assets/mermaid.core-Bbo24DGo.js +0 -11
  273. package/studio/web/assets/notifications-Bb2cj14_.js +0 -1
  274. package/studio/web/assets/notifications-DVlKonbI.js +0 -1
  275. package/studio/web/assets/packet-7NZHBO7P-BGMXB0XL.js +0 -1
  276. package/studio/web/assets/path-fybaL0A-.js +0 -1
  277. package/studio/web/assets/pegDiagram-VL7TDLO6-CWEktcBB.js +0 -1
  278. package/studio/web/assets/pie-RZYD4A2V-DgYg3tCt.js +0 -1
  279. package/studio/web/assets/pieDiagram-7S7Q4E2Y-DEAmZOqY.js +0 -39
  280. package/studio/web/assets/pollUnlessForbidden-DIDXGBc5.js +0 -1
  281. package/studio/web/assets/profile-BSQWfYfq.js +0 -1
  282. package/studio/web/assets/purify.es-DrVcFY1Q.js +0 -3
  283. package/studio/web/assets/queryClient-BLhQvmWC.js +0 -1
  284. package/studio/web/assets/radar-I7S5WNFK-Ag-zp_Rq.js +0 -1
  285. package/studio/web/assets/railroad-3IZDKUUU-aibJDIDV.js +0 -1
  286. package/studio/web/assets/railroad-abnf-AHOZXSZD-BBMEuvIl.js +0 -1
  287. package/studio/web/assets/railroad-ebnf-EBAXGLYW-Be1nseej.js +0 -1
  288. package/studio/web/assets/railroad-peg-LSFZ7HO6-DIvD-Eyb.js +0 -1
  289. package/studio/web/assets/railroadDiagram-AXF67PYL-BJWrgR10.js +0 -1
  290. package/studio/web/assets/react-VeAY02s6.js +0 -1
  291. package/studio/web/assets/react-redux-Ds7wf7Ax.js +0 -5
  292. package/studio/web/assets/regions-Dk3g8bBF.js +0 -1
  293. package/studio/web/assets/register-3F1Tje_F.js +0 -2
  294. package/studio/web/assets/register-S_PdXsoi.js +0 -2
  295. package/studio/web/assets/rolldown-runtime-B0Z9INg1.js +0 -1
  296. package/studio/web/assets/select-CKgJgpkn.js +0 -1
  297. package/studio/web/assets/setComponentFile-DoITgNLb.js +0 -1
  298. package/studio/web/assets/setLocalStorage-CD_L8p_D.js +0 -1
  299. package/studio/web/assets/setup-CiEALLa7.js +0 -2
  300. package/studio/web/assets/src-DUvBCJIr.js +0 -1
  301. package/studio/web/assets/stateDiagram-OKZ733FA-D9oPLTjO.js +0 -1
  302. package/studio/web/assets/stateDiagram-v2-UEYNNEHI-CSD1wbuZ.js +0 -1
  303. package/studio/web/assets/status-CK9tD-Nd.js +0 -61
  304. package/studio/web/assets/string-f6JzSHaO.js +0 -1
  305. package/studio/web/assets/swagger-ui-react-CxjCDFB-.js +0 -240
  306. package/studio/web/assets/swimlanes-SLNWSIFB-BpeoNE9k.js +0 -2
  307. package/studio/web/assets/swimlanesDiagram-ULZ7WXOC-DHxwzxpp.js +0 -8
  308. package/studio/web/assets/table-BvFflPWi.js +0 -1
  309. package/studio/web/assets/tabs-Dd_ElZ36.js +0 -1
  310. package/studio/web/assets/textarea-a3RnTY31.js +0 -9
  311. package/studio/web/assets/toggleHighContrast-CyNC3SCQ.js +0 -49
  312. package/studio/web/assets/tokenization-CWuvR2gh.js +0 -7
  313. package/studio/web/assets/treeView-QDETBFTQ-uHZ-3Fz8.js +0 -1
  314. package/studio/web/assets/treemap-6X3UGDF4-BnUKyy3l.js +0 -1
  315. package/studio/web/assets/tsMode-CslzhcVk.js +0 -11
  316. package/studio/web/assets/typescript-Dtnury3t.js +0 -1
  317. package/studio/web/assets/useAuth-DiJUZS1C.js +0 -1
  318. package/studio/web/assets/useEntityRestURL-Cy-0i1UZ.js +0 -1
  319. package/studio/web/assets/useLocalStorage-DetQlhBe.js +0 -1
  320. package/studio/web/assets/vendor-datadog-XDrpA25D.js +0 -6
  321. package/studio/web/assets/vendor-tanstack-FsM5XZNE.js +0 -1
  322. package/studio/web/assets/wardley-OPB4EBWU-Da7TLC2F.js +0 -1
  323. package/studio/web/assets/workers-BtibQGyk.js +0 -3
  324. package/studio/web/assets/x-D39AGKMb.js +0 -1
  325. package/studio/web/assets/xml-D41zWqPl.js +0 -1
  326. package/studio/web/assets/yaml-BFQ3mF1U.js +0 -1
  327. /package/studio/web/assets/{editor-jjEx9u7D.css → register-jjEx9u7D.css} +0 -0
@@ -36,6 +36,7 @@ import {
36
36
  DatabaseTransaction,
37
37
  ImmediateTransaction,
38
38
  priorStagedWrite,
39
+ isJoinableScope,
39
40
  isReleasedTransaction,
40
41
  TRANSACTION_STATE,
41
42
  writeKeyId,
@@ -71,7 +72,15 @@ import { getWorkerIndex, getWorkerCount } from '../server/threads/manageThreads.
71
72
  import { HAS_BLOBS, auditRetention, removeAuditEntry } from './auditStore.ts';
72
73
  import { buildEmbedBefore, createDefaultEmbedder, type EmbedAttribute, type Embedder } from './models/embedHook.ts';
73
74
  import { autoCast, autoCastBooleanStrict } from '../utility/common_utils.ts';
74
- import { recordUpdater, removeEntry, PENDING_LOCAL_TIME, RecordObject, type Entry, entryMap } from './RecordEncoder.ts';
75
+ import {
76
+ recordUpdater,
77
+ removeEntry,
78
+ PENDING_LOCAL_TIME,
79
+ RecordObject,
80
+ type Entry,
81
+ entryMap,
82
+ storedFieldsOnly,
83
+ } from './RecordEncoder.ts';
75
84
  import { recordAction, recordActionBinary } from './analytics/write.ts';
76
85
  import { rebuildUpdateBefore } from './crdt.ts';
77
86
  import { appendHeader } from '../server/serverHelpers/Headers.ts';
@@ -452,6 +461,18 @@ export function makeTable(options) {
452
461
  // it, so such a table takes the guarded serialization path rather than the raw fast path.
453
462
  let hasSurfacedComputed = false;
454
463
  let runningRecordExpiration: boolean;
464
+ const reportedResolverCollisions = new Set<string>();
465
+ // Reached from record materialization, so it can never be the reason a record fails to load: the
466
+ // name is marked before the log call, and a throwing log sink is swallowed.
467
+ function reportResolverCollision(name: string) {
468
+ if (reportedResolverCollisions.has(name)) return;
469
+ reportedResolverCollisions.add(name);
470
+ try {
471
+ logger.warn?.(
472
+ `Table "${tableName}" has a stored value under "${name}", which is a computed attribute; the stored value is being discarded and the computed value used instead`
473
+ );
474
+ } catch {}
475
+ }
455
476
  const isRocksDB = primaryStore instanceof RocksDatabase;
456
477
  type BigInt64ArrayAndMaxSafeId = BigInt64Array & { maxSafeId: number };
457
478
  let idIncrementer: BigInt64ArrayAndMaxSafeId;
@@ -1873,7 +1894,28 @@ export function makeTable(options) {
1873
1894
  }
1874
1895
  #saveOperation(operation: any) {
1875
1896
  const transaction = txnForContext(this.getContext());
1876
- if (transaction.save) return transaction.save(operation) || operation.promise || operation.result;
1897
+ const holder = operation.stagedIn;
1898
+ // never-drop-on-conflict lives on the transaction and would not travel with the write, so an
1899
+ // apply or a replay keeps it (harper-pro#348)
1900
+ const holderOwnsPolicy = holder?.sourceApply || holder?.isReplay;
1901
+ // stagesWriteOnSave: LMDBTransaction's addWrite never runs the write (its commit applies
1902
+ // `writes`), so handing it one is a dead end
1903
+ if (
1904
+ holder &&
1905
+ holder !== transaction &&
1906
+ !holderOwnsPolicy &&
1907
+ transaction.stagesWriteOnSave &&
1908
+ isJoinableScope(transaction)
1909
+ ) {
1910
+ holder.detachWrite(operation);
1911
+ // The basis chain belongs to the holder: derived from a write this scope cannot commit, the
1912
+ // merge and index diff would be relative to a record that may never land.
1913
+ operation.priorWrite = undefined;
1914
+ operation.deferSave = false;
1915
+ return when(transaction.addWrite(operation), () => operation.promise ?? operation.result);
1916
+ }
1917
+ const owner = holder ?? transaction;
1918
+ if (owner.save) return owner.save(operation) || operation.promise || operation.result;
1877
1919
  }
1878
1920
 
1879
1921
  addTo(property: any, value: any) {
@@ -2314,11 +2356,11 @@ export function makeTable(options) {
2314
2356
  nodeName: (context as any)?.nodeName,
2315
2357
  fullUpdate,
2316
2358
  deferSave: true,
2317
- validate: (txnTime) => {
2359
+ validate: (txnTime, committedBy = transaction) => {
2318
2360
  if (!recordUpdate) recordUpdate = this.#changes;
2319
2361
  if (fullUpdate || (recordUpdate && hasChanges(this.#changes === recordUpdate ? this : recordUpdate))) {
2320
2362
  if (!(context as any)?.source) {
2321
- transaction.checkOverloaded();
2363
+ committedBy.checkOverloaded();
2322
2364
  // A record must be a plain object. Reject primitive, string/number, bare-binary,
2323
2365
  // and bare-array roots — e.g. a raw Buffer from an application/octet-stream PUT, a
2324
2366
  // JSON string/number body, or a top-level JSON array. Such roots carry no primary
@@ -2356,7 +2398,7 @@ export function makeTable(options) {
2356
2398
  // by replayLogs). Records were valid when originally written; post-crash schema
2357
2399
  // evolution (e.g. newly required fields) must not prevent replaying them
2358
2400
  // (harper#1316, facet b).
2359
- if (!transaction.isReplay) this.validate(recordUpdate, !fullUpdate);
2401
+ if (!committedBy.isReplay) this.validate(recordUpdate, !fullUpdate);
2360
2402
  if (updatedTimeProperty) {
2361
2403
  recordUpdate[updatedTimeProperty.name] =
2362
2404
  updatedTimeProperty.type === 'Date'
@@ -2391,7 +2433,7 @@ export function makeTable(options) {
2391
2433
  // TODO: else freeze after we have applied the changes
2392
2434
  }
2393
2435
  } else {
2394
- (transaction as any).removeWrite?.(write);
2436
+ (committedBy as any).removeWrite?.(write);
2395
2437
  return false;
2396
2438
  }
2397
2439
  },
@@ -2434,6 +2476,7 @@ export function makeTable(options) {
2434
2476
  let incrementalUpdateToApply: boolean;
2435
2477
 
2436
2478
  this.#savingOperation = null;
2479
+ write.stagedIn = undefined; // nothing may pin this write's transaction past its commit
2437
2480
  let omitLocalRecord = false;
2438
2481
  // we use optimistic locking to only commit if the existing record state still holds true.
2439
2482
  // this is superior to using an async transaction since it doesn't require JS execution
@@ -4967,6 +5010,9 @@ export function makeTable(options) {
4967
5010
  for (const attribute of this.attributes) {
4968
5011
  if (attribute.isPrimaryKey) primaryKeyAttribute = attribute;
4969
5012
  attribute.resolve = null; // reset this
5013
+ // Also the setter, or a reload that turns a @relationship into a @computed keeps the
5014
+ // relationship's setter and writes a foreign key from a computed assignment.
5015
+ attribute.set = null;
4970
5016
  const relationship = attribute.relationship;
4971
5017
  const computed = attribute.computed;
4972
5018
  // Register the default embedder unless an author override is set. Sits outside
@@ -5128,14 +5174,19 @@ export function makeTable(options) {
5128
5174
  enumerableAttributeNames = [];
5129
5175
  enumerableRelationDefs.clear();
5130
5176
  hasSurfacedComputed = false;
5177
+ const resolvedAttributeNames: string[] = [];
5131
5178
  for (const attribute of attributes) {
5132
5179
  const name = attribute.name;
5133
5180
  if (attribute.resolve) {
5181
+ resolvedAttributeNames.push(name);
5134
5182
  Object.defineProperty(primaryStore.encoder.structPrototype, name, {
5135
5183
  get() {
5136
5184
  return attribute.resolve(this, contextStorage.getStore()); // it is only possible to get the context from ALS, we don't have a direct reference to the current context
5137
5185
  },
5138
5186
  set(related) {
5187
+ // A read-only resolver must never be the reason a record fails to materialize — the
5188
+ // same reason the one-to-many branch above installs a no-op.
5189
+ if (!attribute.set) return reportResolverCollision(name);
5139
5190
  return attribute.set(this, related);
5140
5191
  },
5141
5192
  configurable: true,
@@ -5161,6 +5212,12 @@ export function makeTable(options) {
5161
5212
  if (enumerableAttributeNames.length > 0)
5162
5213
  installEnumerableToJSON(primaryStore.encoder.structPrototype, this, hasSurfacedComputed);
5163
5214
  else if (primaryStore.encoder.structPrototype.toJSON) delete primaryStore.encoder.structPrototype.toJSON;
5215
+ // Undefined rather than an empty set for a table with no resolved attributes: that is the
5216
+ // check which keeps the projection off an unaffected store's write path.
5217
+ primaryStore.encoder.resolvedAttributeNames =
5218
+ resolvedAttributeNames.length > 0 ? new Set(resolvedAttributeNames) : undefined;
5219
+ primaryStore.encoder.resolvedAttributeNamesList = resolvedAttributeNames;
5220
+ primaryStore.encoder.surfacedToJSON = primaryStore.encoder.structPrototype.toJSON;
5164
5221
  }
5165
5222
  // #section: computed-history
5166
5223
  static setComputedAttribute(attribute_name, resolver) {
@@ -5645,10 +5702,33 @@ export function makeTable(options) {
5645
5702
  // See if this is a transaction for our database and if so, use it
5646
5703
  if (transaction.db?.path === primaryStore.path) return transaction;
5647
5704
  // try the next one:
5648
- const nextTxn = transaction.next;
5705
+ let nextTxn = transaction.next;
5706
+ // A self-committing link is CLOSED once it has committed, and a further write through it
5707
+ // commits on a native handle nothing awaits (#2323). Spent — closed, handle detached, none of
5708
+ // its OWN writes left (hasPendingWrites walks successors, which is not this question) — it
5709
+ // holds nothing, so drop it. A run of them can be spent, hence the loop. A timeout-poisoned
5710
+ // link is kept: reusing it is what makes the rest of the operation fail atomically (#1411).
5711
+ while (
5712
+ nextTxn?.saveCommits &&
5713
+ nextTxn.open !== TRANSACTION_STATE.OPEN &&
5714
+ !nextTxn.timedOut &&
5715
+ !nextTxn.transaction &&
5716
+ !nextTxn.writes.some((write) => write)
5717
+ ) {
5718
+ transaction.next = nextTxn.next;
5719
+ nextTxn = transaction.next;
5720
+ }
5649
5721
  if (!nextTxn) {
5650
5722
  // no next one, then add our database
5651
- transaction.next = isRocksDB ? new DatabaseTransaction() : new LMDBTransaction();
5723
+ // A staging link under a self-committing head is committed only if the head's own database
5724
+ // is written again and cascades the chain, so a handler writing this one last loses it (#2292).
5725
+ transaction.next = transaction.saveCommits
5726
+ ? ((isRocksDB
5727
+ ? new ImmediateTransaction(primaryStore as any)
5728
+ : new ImmediateLMDBTransaction(primaryStore as any)) as any)
5729
+ : isRocksDB
5730
+ ? new DatabaseTransaction()
5731
+ : new LMDBTransaction();
5652
5732
  // The chain root, so a link that only ever receives a blind write is supervised by the
5653
5733
  // long-transaction monitor as part of its logical transaction rather than as its own
5654
5734
  // timeout root (issue #2231).
@@ -5670,8 +5750,11 @@ export function makeTable(options) {
5670
5750
  // A second database joined after a mid-scope commit belongs to the same snapshot-free
5671
5751
  // generation as the head, or its reads would re-pin what the commit just unpinned.
5672
5752
  transaction.next.snapshotFree = transaction.snapshotFree;
5673
- if (transaction.open === TRANSACTION_STATE.CLOSED) {
5753
+ if (transaction.open === TRANSACTION_STATE.CLOSED && !transaction.next.saveCommits) {
5674
5754
  // if the current transaction is already closed, we need to retain that state on new databases we work with
5755
+ // Never onto a self-committing link: CLOSED is what routes its first write through the
5756
+ // commit re-entry that drops the native commit promise (#2323), and it commits per write
5757
+ // regardless of this state.
5675
5758
  transaction.next.open = TRANSACTION_STATE.CLOSED;
5676
5759
  }
5677
5760
  transaction = transaction.next;
@@ -5948,6 +6031,31 @@ export function makeTable(options) {
5948
6031
  // before stamping the primary key and created/updated times below (records are immutable —
5949
6032
  // 5.2 record caching relies on it — so we must not write through the frozen object).
5950
6033
  if (isFrozenRecordObject(updatedRecord)) updatedRecord = { ...updatedRecord };
6034
+ // A writable resolver (a relationship) keeps its meaning for source payloads: a source
6035
+ // returning the related object instead of the foreign key gets the key derived, the way
6036
+ // the promotion setter used to. Derivation runs against a probe first — a malformed
6037
+ // value (a scalar, an object without the related primary key) derives undefined, and
6038
+ // applying that would durably wipe the foreign key. The projection then drops the
6039
+ // resolver-owned key itself, so the cache-fill response cannot be the one read
6040
+ // reporting the source's value.
6041
+ const resolvedNames = primaryStore.encoder.resolvedAttributeNamesList;
6042
+ if (resolvedNames) {
6043
+ for (const name of resolvedNames) {
6044
+ if (Object.hasOwn(updatedRecord, name)) {
6045
+ const resolvedAttribute = findAttribute(attributes, name);
6046
+ if (resolvedAttribute?.set && updatedRecord[name] != null) {
6047
+ const probe = {};
6048
+ resolvedAttribute.set(probe, updatedRecord[name]);
6049
+ for (const key in probe) {
6050
+ const derived = probe[key];
6051
+ const usable = Array.isArray(derived) ? derived.every((one) => one != null) : derived != null;
6052
+ if (usable) updatedRecord[key] = derived;
6053
+ }
6054
+ }
6055
+ }
6056
+ }
6057
+ }
6058
+ updatedRecord = storedFieldsOnly(primaryStore.encoder, updatedRecord);
5951
6059
  if (primaryKey && updatedRecord[primaryKey] !== id) updatedRecord[primaryKey] = id;
5952
6060
  }
5953
6061
  resolved = true;
@@ -351,4 +351,4 @@ async function processGraphQLSchema(gqlContent, urlPath, filePath, resources) {
351
351
  }
352
352
 
353
353
  // useful for testing
354
- export const loadGQLSchema = (content) => processGraphQLSchema(content, null, null, new Resources());
354
+ export const loadGQLSchema = (content) => processGraphQLSchema(content, null, '<inline-schema>', new Resources());
@@ -45,6 +45,10 @@ export function assignTrackedAccessors(Target, typeDef, useFullPropertyProxy = f
45
45
  return attribute.resolve(this, this.getContext?.());
46
46
  },
47
47
  set(related) {
48
+ // Unlike the struct-prototype accessor (which tolerates a stored collision so a record can
49
+ // still load), this is a user assignment to a resolved attribute, and a read-only resolver
50
+ // (a scalar @computed has no attribute.set) has nowhere to put it (harper#2359).
51
+ if (!attribute.set) throw new ClientError(`${name} is a computed attribute and can not be assigned`);
48
52
  return attribute.set(this, related);
49
53
  },
50
54
  configurable: true,
@@ -2,9 +2,9 @@ import type { Context } from './ResourceInterface.ts';
2
2
  import { _assignPackageExport } from '../globals.js';
3
3
  import {
4
4
  DatabaseTransaction,
5
+ isJoinableScope,
5
6
  isReleasedTransaction,
6
7
  type Transaction,
7
- TRANSACTION_STATE,
8
8
  } from './DatabaseTransaction.ts';
9
9
  import { AsyncLocalStorage } from 'async_hooks';
10
10
 
@@ -41,7 +41,7 @@ export function transaction<T>(
41
41
  if (typeof callback !== 'function') {
42
42
  throw new TypeError('Callback function must be provided to transaction');
43
43
  }
44
- if (context?.transaction?.open === TRANSACTION_STATE.OPEN && typeof callback === 'function') {
44
+ if (isJoinableScope(context?.transaction) && typeof callback === 'function') {
45
45
  return callback(context.transaction); // nothing to be done, already in open transaction
46
46
  }
47
47
 
package/server/DESIGN.md CHANGED
@@ -68,6 +68,12 @@ A request entering `http.ts` does **not** go through Fastify. The two `handleApp
68
68
  | `threads/itc.js` | Inter-thread comms primitives. |
69
69
  | `transactionLogCooling.ts` | Main-thread timer that cools transaction-log mmaps. |
70
70
 
71
+ Process-wide shutdown begins by calling `beginProcessShutdown()` in `threads/manageThreads.js`.
72
+ Once set, this terminal state prevents every worker replacement path and makes new `startWorker()`
73
+ calls fail with `ERR_HARPER_PROCESS_SHUTTING_DOWN`; scoped worker-type restarts do not set it.
74
+ `shutdownWorkersNow()` remains an immediate teardown: its worker shutdown messages are best-effort,
75
+ and it force-terminates the remaining worker set rather than waiting for application drain hooks.
76
+
71
77
  > Workers receive `workerData.noServerStart = true` — never start the server inside a worker.
72
78
  >
73
79
  > `threadServer.listenOnDomainSocket()` skips a listener only when its path exceeds the platform's
@@ -46,6 +46,7 @@ const chokidar = require('chokidar');
46
46
  const isBun = typeof globalThis.Bun !== 'undefined';
47
47
  const MB = 1024 * 1024;
48
48
  const workers = []; // these are our child workers that we are managing
49
+ let processShuttingDown = false;
49
50
  const connectedPorts = []; // these are all known connected worker ports (siblings, children, parents)
50
51
  const MAX_UNEXPECTED_RESTARTS = 50;
51
52
  // Threads get 10s to die before they're forced. In dev (`harper dev`) we widen this: a reload's old
@@ -150,6 +151,7 @@ module.exports = {
150
151
  setTerminateTimeout,
151
152
  extendShutdownDeadline,
152
153
  restoreShutdownDeadline,
154
+ beginProcessShutdown,
153
155
  registerWorkerDataProvider,
154
156
  onThreadExit,
155
157
  registerProcessGroup,
@@ -324,6 +326,11 @@ listenersByType.set(THREAD_INFO, null);
324
326
  listenersByType.set(PROCESS_GROUP_TERMINATION_CONFIRMED, null);
325
327
 
326
328
  function startWorker(path, options = {}) {
329
+ if (processShuttingDown) {
330
+ const error = new Error('Cannot start a worker while the Harper process is shutting down');
331
+ error.code = 'ERR_HARPER_PROCESS_SHUTTING_DOWN';
332
+ throw error;
333
+ }
327
334
  // Take a percentage of total memory to determine the max memory for each thread. The percentage is based
328
335
  // on the thread count. Generally, it is unrealistic to efficiently use the majority of total memory for a single
329
336
  // NodeJS worker since it would lead to massive swap space usage with other processes and there is significant
@@ -435,7 +442,7 @@ function startWorker(path, options = {}) {
435
442
  });
436
443
  worker.on('exit', (_code) => {
437
444
  workers.splice(workers.indexOf(worker), 1);
438
- if (!worker.wasShutdown && options.autoRestart !== false) {
445
+ if (!processShuttingDown && !worker.wasShutdown && options.autoRestart !== false) {
439
446
  // if this wasn't an intentional shutdown, restart now (unless we have tried too many times)
440
447
  if (worker.unexpectedRestarts < MAX_UNEXPECTED_RESTARTS) {
441
448
  options.unexpectedRestarts = worker.unexpectedRestarts + 1;
@@ -469,6 +476,7 @@ async function restartWorkers(
469
476
  startReplacementThreads = true
470
477
  ) {
471
478
  if (isMainThread) {
479
+ if (processShuttingDown && startReplacementThreads) return;
472
480
  try {
473
481
  // we do this because it is possible for a component to chdir to itself, get re-deployed and then the cwd
474
482
  // inode link is invalid and it can cause a lot of problems. But process.cwd() still returns the path, for
@@ -506,6 +514,8 @@ async function restartWorkers(
506
514
  // listenOnPorts() treat a dedicated listener's EADDRINUSE as an external conflict.
507
515
  const canPreStartReplacement = process.platform !== 'win32' && process.platform !== 'darwin' && !isBun;
508
516
  for (let worker of workers.slice(0)) {
517
+ // Terminal shutdown: stop replacing workers mid-loop — the guard for every replacement start below.
518
+ if (processShuttingDown && startReplacementThreads) break;
509
519
  if ((name && worker.name !== name) || worker.wasShutdown) continue; // filter by type, if specified
510
520
  const overlapping = OVERLAPPING_RESTART_TYPES.indexOf(worker.name) > -1;
511
521
  if (overlapping && startReplacementThreads && canPreStartReplacement) {
@@ -590,7 +600,7 @@ async function restartWorkers(
590
600
  // Overlapping types we couldn't pre-start (Windows/Bun): start the replacement now that the old
591
601
  // worker is releasing its port. server.close() stops accepting immediately, so the port frees up
592
602
  // well before the replacement finishes booting and binds.
593
- if (overlapping && startReplacementThreads && !canPreStartReplacement) worker.startCopy();
603
+ if (overlapping && startReplacementThreads && !canPreStartReplacement && !processShuttingDown) worker.startCopy();
594
604
  let whenDone = new Promise((resolve) => {
595
605
  // in case the exit inside the thread doesn't timeout, force it from the outside
596
606
  const armTerminate = (delay) =>
@@ -627,7 +637,7 @@ async function restartWorkers(
627
637
  const index = waitingToFinish.indexOf(whenDone);
628
638
  if (index > -1) waitingToFinish.splice(index, 1);
629
639
  // non-overlapping types have no advance replacement, so start it once the old one is gone
630
- if (!overlapping && startReplacementThreads) worker.startCopy();
640
+ if (!overlapping && startReplacementThreads && !processShuttingDown) worker.startCopy();
631
641
  resolve();
632
642
  });
633
643
  });
@@ -650,7 +660,11 @@ async function restartWorkers(
650
660
  function shutdownWorkers(name) {
651
661
  return restartWorkers(name, Infinity, false);
652
662
  }
663
+ function beginProcessShutdown() {
664
+ processShuttingDown = true;
665
+ }
653
666
  async function shutdownWorkersNow(name) {
667
+ if (name == null) beginProcessShutdown();
654
668
  shutdownWorkers(name); // set the state of all the workers to shut down. this should finish the important stuff synchronously
655
669
  if (isBun) {
656
670
  // worker.terminate() triggers a NAPI segfault in Bun; ask workers to self-exit instead