@aeolus-fleet/gateway 0.38.1 → 0.38.3

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 (319) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/prisma/fleet-forgetter.d.ts +1 -1
  3. package/dist/adapters/prisma/fleet-forgetter.js +2 -2
  4. package/dist/adapters/prisma/fleet-forgetter.js.map +1 -1
  5. package/dist/adapters/prisma/generated/browser.d.ts +10 -0
  6. package/dist/adapters/prisma/generated/client.d.ts +10 -0
  7. package/dist/adapters/prisma/generated/internal/class.d.ts +22 -0
  8. package/dist/adapters/prisma/generated/internal/class.js +4 -4
  9. package/dist/adapters/prisma/generated/internal/class.js.map +1 -1
  10. package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +172 -1
  11. package/dist/adapters/prisma/generated/internal/prismaNamespace.js +19 -0
  12. package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -1
  13. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +21 -0
  14. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +19 -0
  15. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  16. package/dist/adapters/prisma/generated/models/QuietHours.d.ts +1102 -0
  17. package/dist/adapters/prisma/generated/models/QuietHours.js +2 -0
  18. package/dist/adapters/prisma/generated/models/QuietHours.js.map +1 -0
  19. package/dist/adapters/prisma/generated/models/QuietShip.d.ts +1031 -0
  20. package/dist/adapters/prisma/generated/models/QuietShip.js +2 -0
  21. package/dist/adapters/prisma/generated/models/QuietShip.js.map +1 -0
  22. package/dist/adapters/prisma/generated/models.d.ts +2 -0
  23. package/dist/adapters/prisma/quiet-preferences.d.ts +12 -0
  24. package/dist/adapters/prisma/quiet-preferences.js +49 -0
  25. package/dist/adapters/prisma/quiet-preferences.js.map +1 -0
  26. package/dist/adapters/trpc/router.d.ts +86 -0
  27. package/dist/adapters/trpc/router.js +37 -0
  28. package/dist/adapters/trpc/router.js.map +1 -1
  29. package/dist/app.js +17 -2
  30. package/dist/app.js.map +1 -1
  31. package/dist/core/argo-inbox/wake-for-argo.d.ts +3 -1
  32. package/dist/core/argo-inbox/wake-for-argo.js +10 -2
  33. package/dist/core/argo-inbox/wake-for-argo.js.map +1 -1
  34. package/dist/core/people/inbox-entry.d.ts +3 -1
  35. package/dist/core/people/inbox-entry.js +2 -2
  36. package/dist/core/people/inbox-entry.js.map +1 -1
  37. package/dist/core/people/person-wakes.d.ts +9 -2
  38. package/dist/core/people/person-wakes.js +10 -2
  39. package/dist/core/people/person-wakes.js.map +1 -1
  40. package/dist/core/people/quiet-hours.d.ts +40 -0
  41. package/dist/core/people/quiet-hours.js +65 -0
  42. package/dist/core/people/quiet-hours.js.map +1 -0
  43. package/dist/core/people/quiet-ships.d.ts +40 -0
  44. package/dist/core/people/quiet-ships.js +24 -0
  45. package/dist/core/people/quiet-ships.js.map +1 -0
  46. package/dist/core/people/read-item.d.ts +31 -0
  47. package/dist/core/people/read-item.js +77 -0
  48. package/dist/core/people/read-item.js.map +1 -0
  49. package/dist/core/people/read-quiet-among.d.ts +15 -0
  50. package/dist/core/people/read-quiet-among.js +15 -0
  51. package/dist/core/people/read-quiet-among.js.map +1 -0
  52. package/dist/core/people/read-quiet-hours.d.ts +30 -0
  53. package/dist/core/people/read-quiet-hours.js +35 -0
  54. package/dist/core/people/read-quiet-hours.js.map +1 -0
  55. package/dist/core/people/read-quiet-ships.d.ts +26 -0
  56. package/dist/core/people/read-quiet-ships.js +19 -0
  57. package/dist/core/people/read-quiet-ships.js.map +1 -0
  58. package/dist/core/people/set-quiet-hours.d.ts +21 -0
  59. package/dist/core/people/set-quiet-hours.js +24 -0
  60. package/dist/core/people/set-quiet-hours.js.map +1 -0
  61. package/dist/core/people/turn-ship-quiet.d.ts +24 -0
  62. package/dist/core/people/turn-ship-quiet.js +25 -0
  63. package/dist/core/people/turn-ship-quiet.js.map +1 -0
  64. package/dist/core/people/wake-person.d.ts +10 -1
  65. package/dist/core/people/wake-person.js +18 -2
  66. package/dist/core/people/wake-person.js.map +1 -1
  67. package/dist/core/shared/errors.d.ts +1 -1
  68. package/dist/core/shared/errors.js.map +1 -1
  69. package/package.json +1 -1
  70. package/src/adapters/prisma/migrations/20261111090000_quiet_preferences/migration.sql +27 -0
  71. package/src/adapters/prisma/schema.prisma +28 -0
  72. package/web/.next/BUILD_ID +1 -1
  73. package/web/.next/build-manifest.json +3 -3
  74. package/web/.next/diagnostics/route-bundle-stats.json +73 -73
  75. package/web/.next/fallback-build-manifest.json +3 -3
  76. package/web/.next/prerender-manifest.json +3 -3
  77. package/web/.next/server/app/(bridge)/bridge/basket/page/server-reference-manifest.json +10 -10
  78. package/web/.next/server/app/(bridge)/bridge/basket/page.js.nft.json +1 -1
  79. package/web/.next/server/app/(bridge)/bridge/basket/page_client-reference-manifest.js +1 -1
  80. package/web/.next/server/app/(bridge)/bridge/done/page/server-reference-manifest.json +4 -4
  81. package/web/.next/server/app/(bridge)/bridge/done/page.js.nft.json +1 -1
  82. package/web/.next/server/app/(bridge)/bridge/done/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/(bridge)/bridge/fleet/page/server-reference-manifest.json +3 -3
  84. package/web/.next/server/app/(bridge)/bridge/fleet/page.js.nft.json +1 -1
  85. package/web/.next/server/app/(bridge)/bridge/fleet/page_client-reference-manifest.js +1 -1
  86. package/web/.next/server/app/(bridge)/bridge/messages/page/server-reference-manifest.json +11 -11
  87. package/web/.next/server/app/(bridge)/bridge/messages/page.js.nft.json +1 -1
  88. package/web/.next/server/app/(bridge)/bridge/messages/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/app/(bridge)/bridge/page/server-reference-manifest.json +10 -10
  90. package/web/.next/server/app/(bridge)/bridge/page.js.nft.json +1 -1
  91. package/web/.next/server/app/(bridge)/bridge/page_client-reference-manifest.js +1 -1
  92. package/web/.next/server/app/(bridge)/bridge/settings/page/server-reference-manifest.json +3 -3
  93. package/web/.next/server/app/(bridge)/bridge/settings/page.js.nft.json +1 -1
  94. package/web/.next/server/app/(bridge)/bridge/settings/page_client-reference-manifest.js +1 -1
  95. package/web/.next/server/app/(bridge)/bridge/settings/requests/[requestId]/page/server-reference-manifest.json +4 -4
  96. package/web/.next/server/app/(bridge)/bridge/settings/requests/[requestId]/page.js.nft.json +1 -1
  97. package/web/.next/server/app/(bridge)/bridge/settings/requests/[requestId]/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app/(bridge)/bridge/settings/routing/page/server-reference-manifest.json +7 -7
  99. package/web/.next/server/app/(bridge)/bridge/settings/routing/page.js.nft.json +1 -1
  100. package/web/.next/server/app/(bridge)/bridge/settings/routing/page_client-reference-manifest.js +1 -1
  101. package/web/.next/server/app/(bridge)/bridge/stay-aware/page/server-reference-manifest.json +10 -10
  102. package/web/.next/server/app/(bridge)/bridge/stay-aware/page.js.nft.json +1 -1
  103. package/web/.next/server/app/(bridge)/bridge/stay-aware/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/(bridge)/outside-parties/[name]/change/page/server-reference-manifest.json +19 -19
  105. package/web/.next/server/app/(bridge)/outside-parties/[name]/change/page.js.nft.json +1 -1
  106. package/web/.next/server/app/(bridge)/outside-parties/[name]/change/page_client-reference-manifest.js +1 -1
  107. package/web/.next/server/app/(bridge)/outside-parties/[name]/page/server-reference-manifest.json +10 -10
  108. package/web/.next/server/app/(bridge)/outside-parties/[name]/page.js.nft.json +1 -1
  109. package/web/.next/server/app/(bridge)/outside-parties/[name]/page_client-reference-manifest.js +1 -1
  110. package/web/.next/server/app/(bridge)/outside-parties/[name]/retire/page/server-reference-manifest.json +19 -19
  111. package/web/.next/server/app/(bridge)/outside-parties/[name]/retire/page.js.nft.json +1 -1
  112. package/web/.next/server/app/(bridge)/outside-parties/[name]/retire/page_client-reference-manifest.js +1 -1
  113. package/web/.next/server/app/(bridge)/outside-parties/add/page/server-reference-manifest.json +12 -12
  114. package/web/.next/server/app/(bridge)/outside-parties/add/page.js.nft.json +1 -1
  115. package/web/.next/server/app/(bridge)/outside-parties/add/page_client-reference-manifest.js +1 -1
  116. package/web/.next/server/app/(bridge)/outside-parties/add-a2a-agent/page/server-reference-manifest.json +4 -4
  117. package/web/.next/server/app/(bridge)/outside-parties/add-a2a-agent/page.js.nft.json +1 -1
  118. package/web/.next/server/app/(bridge)/outside-parties/add-a2a-agent/page_client-reference-manifest.js +1 -1
  119. package/web/.next/server/app/(bridge)/outside-parties/add-a2a-client/page/server-reference-manifest.json +4 -4
  120. package/web/.next/server/app/(bridge)/outside-parties/add-a2a-client/page.js.nft.json +1 -1
  121. package/web/.next/server/app/(bridge)/outside-parties/add-a2a-client/page_client-reference-manifest.js +1 -1
  122. package/web/.next/server/app/(bridge)/outside-parties/page/server-reference-manifest.json +4 -4
  123. package/web/.next/server/app/(bridge)/outside-parties/page.js.nft.json +1 -1
  124. package/web/.next/server/app/(bridge)/outside-parties/page_client-reference-manifest.js +1 -1
  125. package/web/.next/server/app/(console)/gateway-off/page/server-reference-manifest.json +1 -1
  126. package/web/.next/server/app/(console)/gateway-off/page.js.nft.json +1 -1
  127. package/web/.next/server/app/(console)/gateway-off/page_client-reference-manifest.js +1 -1
  128. package/web/.next/server/app/(console)/meetings/[meetingId]/page/server-reference-manifest.json +3 -3
  129. package/web/.next/server/app/(console)/meetings/[meetingId]/page.js.nft.json +1 -1
  130. package/web/.next/server/app/(console)/meetings/[meetingId]/page_client-reference-manifest.js +1 -1
  131. package/web/.next/server/app/(console)/parties/page/server-reference-manifest.json +9 -9
  132. package/web/.next/server/app/(console)/parties/page.js.nft.json +1 -1
  133. package/web/.next/server/app/(console)/parties/page_client-reference-manifest.js +1 -1
  134. package/web/.next/server/app/(console)/sign-in/failed/page/server-reference-manifest.json +1 -1
  135. package/web/.next/server/app/(console)/sign-in/failed/page.js.nft.json +1 -1
  136. package/web/.next/server/app/(console)/sign-in/failed/page_client-reference-manifest.js +1 -1
  137. package/web/.next/server/app/(console)/slack/disconnect/page/server-reference-manifest.json +9 -9
  138. package/web/.next/server/app/(console)/slack/disconnect/page.js.nft.json +1 -1
  139. package/web/.next/server/app/(console)/slack/disconnect/page_client-reference-manifest.js +1 -1
  140. package/web/.next/server/app/(console)/slack/expose/page/server-reference-manifest.json +9 -9
  141. package/web/.next/server/app/(console)/slack/expose/page.js.nft.json +1 -1
  142. package/web/.next/server/app/(console)/slack/expose/page_client-reference-manifest.js +1 -1
  143. package/web/.next/server/app/(console)/slack/page/server-reference-manifest.json +9 -9
  144. package/web/.next/server/app/(console)/slack/page.js.nft.json +1 -1
  145. package/web/.next/server/app/(console)/slack/page_client-reference-manifest.js +1 -1
  146. package/web/.next/server/app/(console)/slack/remove/page/server-reference-manifest.json +9 -9
  147. package/web/.next/server/app/(console)/slack/remove/page.js.nft.json +1 -1
  148. package/web/.next/server/app/(console)/slack/remove/page_client-reference-manifest.js +1 -1
  149. package/web/.next/server/app/_global-error.html +1 -1
  150. package/web/.next/server/app/_global-error.rsc +1 -1
  151. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  152. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  153. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  154. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  155. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  156. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  157. package/web/.next/server/app/authorize/failed/page/server-reference-manifest.json +1 -1
  158. package/web/.next/server/app/authorize/failed/page.js.nft.json +1 -1
  159. package/web/.next/server/app/authorize/failed/page_client-reference-manifest.js +1 -1
  160. package/web/.next/server/app/authorize/pick/page/server-reference-manifest.json +1 -1
  161. package/web/.next/server/app/authorize/pick/page.js.nft.json +1 -1
  162. package/web/.next/server/app/authorize/pick/page_client-reference-manifest.js +1 -1
  163. package/web/.next/server/app/authorize/waiting/approval/page/server-reference-manifest.json +1 -1
  164. package/web/.next/server/app/authorize/waiting/approval/page.js.nft.json +1 -1
  165. package/web/.next/server/app/authorize/waiting/approval/page_client-reference-manifest.js +1 -1
  166. package/web/.next/server/chunks/ssr/01fr_app_(bridge)_bridge_settings_requests_[requestId]_page_actions_0o8g7_xshtmem.js +1 -1
  167. package/web/.next/server/chunks/ssr/01fr_app_(bridge)_bridge_settings_requests_[requestId]_page_actions_0o8g7_xshtmem.js.map +1 -1
  168. package/web/.next/server/chunks/ssr/0b9d__next-internal_server_app_(bridge)_bridge_messages_page_actions_1tg2-lw0i6g9l.js +1 -1
  169. package/web/.next/server/chunks/ssr/0b9d__next-internal_server_app_(bridge)_bridge_messages_page_actions_1tg2-lw0i6g9l.js.map +1 -1
  170. package/web/.next/server/chunks/ssr/0b9d__next-internal_server_app_(bridge)_bridge_settings_page_actions_0_te6h-2xxp7l.js +1 -1
  171. package/web/.next/server/chunks/ssr/0b9d__next-internal_server_app_(bridge)_bridge_settings_page_actions_0_te6h-2xxp7l.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/0b9d__next-internal_server_app_(bridge)_bridge_stay-aware_page_actions_1u0xo0v3y9c34.js +1 -1
  173. package/web/.next/server/chunks/ssr/0b9d__next-internal_server_app_(bridge)_bridge_stay-aware_page_actions_1u0xo0v3y9c34.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_bridge_settings_routing_page_actions_06_j7s24dy5ee.js +1 -1
  175. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_bridge_settings_routing_page_actions_06_j7s24dy5ee.js.map +1 -1
  176. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_[name]_change_page_actions_1is-kjq5bubl4.js +1 -1
  177. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_[name]_change_page_actions_1is-kjq5bubl4.js.map +1 -1
  178. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_[name]_page_actions_1mctxtlzsa7xi.js +1 -1
  179. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_[name]_page_actions_1mctxtlzsa7xi.js.map +1 -1
  180. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_[name]_retire_page_actions_0xh6ok1un7s9k.js +1 -1
  181. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_[name]_retire_page_actions_0xh6ok1un7s9k.js.map +1 -1
  182. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_add-a2a-agent_page_actions_1w1q5eavo_loo.js +1 -1
  183. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_add-a2a-agent_page_actions_1w1q5eavo_loo.js.map +1 -1
  184. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_add_page_actions_0urcbg_r0lo7j.js +1 -1
  185. package/web/.next/server/chunks/ssr/0vkm_server_app_(bridge)_outside-parties_add_page_actions_0urcbg_r0lo7j.js.map +1 -1
  186. package/web/.next/server/chunks/ssr/[root-of-the-server]__04g-10_lwy-l2._.js +1 -1
  187. package/web/.next/server/chunks/ssr/[root-of-the-server]__0geojgpilsx6e._.js +1 -1
  188. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ktja-0332icp._.js +1 -1
  189. package/web/.next/server/chunks/ssr/[root-of-the-server]__0m_acooerfxfb._.js +1 -1
  190. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ovcg5tg3nh49._.js +1 -1
  191. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ovcg5tg3nh49._.js.map +1 -1
  192. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ro-majrw7piv._.js +1 -1
  193. package/web/.next/server/chunks/ssr/[root-of-the-server]__0ro-majrw7piv._.js.map +1 -1
  194. package/web/.next/server/chunks/ssr/[root-of-the-server]__0zz6fx0keti4r._.js +1 -1
  195. package/web/.next/server/chunks/ssr/[root-of-the-server]__0zz6fx0keti4r._.js.map +1 -1
  196. package/web/.next/server/chunks/ssr/[root-of-the-server]__14hg5j_bmrdxt._.js +1 -1
  197. package/web/.next/server/chunks/ssr/[root-of-the-server]__18-8taiduk1jn._.js +1 -1
  198. package/web/.next/server/chunks/ssr/[root-of-the-server]__18-8taiduk1jn._.js.map +1 -1
  199. package/web/.next/server/chunks/ssr/[root-of-the-server]__19p4g16n2nh0b._.js +1 -1
  200. package/web/.next/server/chunks/ssr/[root-of-the-server]__19p4g16n2nh0b._.js.map +1 -1
  201. package/web/.next/server/chunks/ssr/[root-of-the-server]__1ncn4wx-1i09m._.js +1 -1
  202. package/web/.next/server/chunks/ssr/[root-of-the-server]__1ncn4wx-1i09m._.js.map +1 -1
  203. package/web/.next/server/chunks/ssr/[root-of-the-server]__1odtiyyqa5vlq._.js +1 -1
  204. package/web/.next/server/chunks/ssr/[root-of-the-server]__1vrtfw4dxnfxt._.js +1 -1
  205. package/web/.next/server/chunks/ssr/_00hfzlqn1og18._.js +1 -1
  206. package/web/.next/server/chunks/ssr/_00hfzlqn1og18._.js.map +1 -1
  207. package/web/.next/server/chunks/ssr/_0_nfv33ug5g31._.js +1 -1
  208. package/web/.next/server/chunks/ssr/_0_nfv33ug5g31._.js.map +1 -1
  209. package/web/.next/server/chunks/ssr/_0ka_9elusb800._.js +1 -1
  210. package/web/.next/server/chunks/ssr/_0ka_9elusb800._.js.map +1 -1
  211. package/web/.next/server/chunks/ssr/{_08jq3ga73wgy1._.js → _0nz6sbd5qnb97._.js} +2 -2
  212. package/web/.next/server/chunks/ssr/{_08jq3ga73wgy1._.js.map → _0nz6sbd5qnb97._.js.map} +1 -1
  213. package/web/.next/server/chunks/ssr/_0pyd1_y7w8ngp._.js +1 -1
  214. package/web/.next/server/chunks/ssr/_0pyd1_y7w8ngp._.js.map +1 -1
  215. package/web/.next/server/chunks/ssr/{_090owdv-b-luu._.js → _0tvjhfjjhmllr._.js} +2 -2
  216. package/web/.next/server/chunks/ssr/{_090owdv-b-luu._.js.map → _0tvjhfjjhmllr._.js.map} +1 -1
  217. package/web/.next/server/chunks/ssr/_0xickgbbju_9-._.js +1 -1
  218. package/web/.next/server/chunks/ssr/_0xickgbbju_9-._.js.map +1 -1
  219. package/web/.next/server/chunks/ssr/{_0cbvl92sxxpsf._.js → _13b33o-hvhs42._.js} +2 -2
  220. package/web/.next/server/chunks/ssr/{_0cbvl92sxxpsf._.js.map → _13b33o-hvhs42._.js.map} +1 -1
  221. package/web/.next/server/chunks/ssr/_1cs_0d0h7mhw0._.js +1 -1
  222. package/web/.next/server/chunks/ssr/_1cs_0d0h7mhw0._.js.map +1 -1
  223. package/web/.next/server/chunks/ssr/{_0t-yyzc3pbo8m._.js → _1j8eks4eyxdp2._.js} +2 -2
  224. package/web/.next/server/chunks/ssr/{_0t-yyzc3pbo8m._.js.map → _1j8eks4eyxdp2._.js.map} +1 -1
  225. package/web/.next/server/chunks/ssr/_1l2qxsuvs6qro._.js +3 -0
  226. package/web/.next/server/chunks/ssr/{_0239h2ocqyibp._.js.map → _1l2qxsuvs6qro._.js.map} +1 -1
  227. package/web/.next/server/chunks/ssr/_1pd7s9yymb567._.js +57 -0
  228. package/web/.next/server/chunks/ssr/_1pd7s9yymb567._.js.map +1 -0
  229. package/web/.next/server/chunks/ssr/_1pjtire7rqla0._.js +1 -1
  230. package/web/.next/server/chunks/ssr/_1pjtire7rqla0._.js.map +1 -1
  231. package/web/.next/server/chunks/ssr/_1preuo1e_lntw._.js +3 -0
  232. package/web/.next/server/chunks/ssr/{_087cuueeby0hw._.js.map → _1preuo1e_lntw._.js.map} +1 -1
  233. package/web/.next/server/chunks/ssr/_1qbsmlji34yph._.js +1 -1
  234. package/web/.next/server/chunks/ssr/_1qbsmlji34yph._.js.map +1 -1
  235. package/web/.next/server/chunks/ssr/_20soyq-dwc131._.js +57 -0
  236. package/web/.next/server/chunks/ssr/_20soyq-dwc131._.js.map +1 -0
  237. package/web/.next/server/chunks/ssr/web_0a9n7acgjrk5c._.js +1 -1
  238. package/web/.next/server/chunks/ssr/web_0a9n7acgjrk5c._.js.map +1 -1
  239. package/web/.next/server/chunks/ssr/web_1vvrekkq5mirt._.js +1 -1
  240. package/web/.next/server/chunks/ssr/web_1vvrekkq5mirt._.js.map +1 -1
  241. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_basket_page_actions_0g7q_rc5nma1e.js +1 -1
  242. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_basket_page_actions_0g7q_rc5nma1e.js.map +1 -1
  243. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_done_page_actions_0kjm34arntdzv.js +1 -1
  244. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_done_page_actions_0kjm34arntdzv.js.map +1 -1
  245. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_fleet_page_actions_19wmo6phgvqfk.js +1 -1
  246. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_fleet_page_actions_19wmo6phgvqfk.js.map +1 -1
  247. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_page_actions_1ok64rg3edm_u.js +1 -1
  248. package/web/.next/server/chunks/ssr/web__next-internal_server_app_(bridge)_bridge_page_actions_1ok64rg3edm_u.js.map +1 -1
  249. package/web/.next/server/chunks/ssr/{web_features_0fji0qhw-fk8x._.js → web_features_0r6fdx9tk4lfm._.js} +2 -2
  250. package/web/.next/server/chunks/ssr/{web_features_0fji0qhw-fk8x._.js.map → web_features_0r6fdx9tk4lfm._.js.map} +1 -1
  251. package/web/.next/server/chunks/ssr/{web_features_1tbi4ma6mufmp._.js → web_features_115v4ed7e_b-8._.js} +2 -2
  252. package/web/.next/server/chunks/ssr/{web_features_1tbi4ma6mufmp._.js.map → web_features_115v4ed7e_b-8._.js.map} +1 -1
  253. package/web/.next/server/chunks/ssr/web_features_add-a2a-agent_ui_a2a-agent-form_tsx_0z8t1aalwzyl7._.js +1 -1
  254. package/web/.next/server/chunks/ssr/web_features_add-a2a-agent_ui_a2a-agent-form_tsx_0z8t1aalwzyl7._.js.map +1 -1
  255. package/web/.next/server/chunks/ssr/web_features_add-a2a-client_ui_a2a-client-form_tsx_1anv88g385nwe._.js +1 -1
  256. package/web/.next/server/chunks/ssr/web_features_add-a2a-client_ui_a2a-client-form_tsx_1anv88g385nwe._.js.map +1 -1
  257. package/web/.next/server/chunks/ssr/web_features_add-server_ui_add-server_tsx_1jnmar5xju49k._.js +1 -1
  258. package/web/.next/server/chunks/ssr/web_features_add-server_ui_add-server_tsx_1jnmar5xju49k._.js.map +1 -1
  259. package/web/.next/server/chunks/ssr/{web_features_bridge_0zkl4uc3a1wa6._.js → web_features_bridge_0cugt1x2wt4m0._.js} +2 -2
  260. package/web/.next/server/chunks/ssr/{web_features_bridge_0zkl4uc3a1wa6._.js.map → web_features_bridge_0cugt1x2wt4m0._.js.map} +1 -1
  261. package/web/.next/server/chunks/ssr/web_features_bridge_hooks_bridge-actions_ts_0h-_xm2rcb-ij._.js +1 -1
  262. package/web/.next/server/chunks/ssr/web_features_bridge_state_basket-panel_tsx_1qi_kzld0rfgs._.js +1 -1
  263. package/web/.next/server/chunks/ssr/web_features_bridge_state_basket-panel_tsx_1qi_kzld0rfgs._.js.map +1 -1
  264. package/web/.next/server/chunks/ssr/web_features_bridge_state_decision-panel_tsx_1mzsixgc8zuxc._.js +1 -1
  265. package/web/.next/server/chunks/ssr/web_features_bridge_state_decision-panel_tsx_1mzsixgc8zuxc._.js.map +1 -1
  266. package/web/.next/server/chunks/ssr/web_features_bridge_state_done-panel_tsx_1m844-qb1z9p_._.js +1 -1
  267. package/web/.next/server/chunks/ssr/web_features_bridge_state_done-panel_tsx_1m844-qb1z9p_._.js.map +1 -1
  268. package/web/.next/server/chunks/ssr/web_features_bridge_state_message-rows_tsx_1ky4-xa4az_yu._.js +1 -1
  269. package/web/.next/server/chunks/ssr/web_features_bridge_state_message-rows_tsx_1ky4-xa4az_yu._.js.map +1 -1
  270. package/web/.next/server/chunks/ssr/web_features_bridge_state_messages-panel_tsx_1yvr_ww639d25._.js +1 -1
  271. package/web/.next/server/chunks/ssr/web_features_bridge_state_messages-panel_tsx_1yvr_ww639d25._.js.map +1 -1
  272. package/web/.next/server/chunks/ssr/web_features_meeting_state_meeting-controls_tsx_12g4kzk2mbvvz._.js +1 -1
  273. package/web/.next/server/chunks/ssr/web_features_meeting_state_meeting-controls_tsx_12g4kzk2mbvvz._.js.map +1 -1
  274. package/web/.next/server/chunks/ssr/web_features_outside-parties_ui_switch-card_tsx_1_xnu9bm4tc-_._.js +1 -1
  275. package/web/.next/server/chunks/ssr/web_features_outside-parties_ui_switch-card_tsx_1_xnu9bm4tc-_._.js.map +1 -1
  276. package/web/.next/server/chunks/ssr/web_features_outside-party_actions_ts_102ar5pdowf8s._.js +1 -1
  277. package/web/.next/server/chunks/ssr/web_features_parties_actions_ts_0r-tbfsig2ty-._.js +1 -1
  278. package/web/.next/server/chunks/ssr/web_features_slack_actions_ts_1l3yg9vl20_vu._.js +1 -1
  279. package/web/.next/server/middleware-build-manifest.js +3 -3
  280. package/web/.next/server/pages/500.html +1 -1
  281. package/web/.next/server/preview-props.json +3 -3
  282. package/web/.next/server/server-reference-manifest.js +1 -1
  283. package/web/.next/server/server-reference-manifest.json +51 -51
  284. package/web/.next/static/chunks/{0pypj0_ydhccr.js → 0-r1bwsrnja6x.js} +1 -1
  285. package/web/.next/static/chunks/{2vaqwkb5z2wz8.js → 0fm-6zl5hm5-9.js} +1 -1
  286. package/web/.next/static/chunks/{3nifwjh6pf2oa.js → 0iu2ts1oy1nzi.js} +1 -1
  287. package/web/.next/static/chunks/{0t63w7558fw1a.js → 0yx6w-_36c76d.js} +1 -1
  288. package/web/.next/static/chunks/1mke3ztpr-wmu.js +1 -0
  289. package/web/.next/static/chunks/1nicl2mkstipv.js +1 -0
  290. package/web/.next/static/chunks/{36ccnz8nhzbm0.js → 1t0fq-vepg52w.js} +1 -1
  291. package/web/.next/static/chunks/{2w5o8qcjwdoqm.js → 1xzhbir4zphli.js} +1 -1
  292. package/web/.next/static/chunks/1zy3y1lvr38g4.js +1 -0
  293. package/web/.next/static/chunks/{2h3yztsbjw8sd.js → 2-wl7cajj-ynx.js} +1 -1
  294. package/web/.next/static/chunks/{1js-1nyhxr0b3.js → 2a8ce88qvmtth.js} +1 -1
  295. package/web/.next/static/chunks/{0-mbc7l-ce37z.js → 2o5u1c-wzvbgm.js} +1 -1
  296. package/web/.next/static/chunks/{3a347eh56u6w0.js → 2rtc0exjb6w5l.js} +1 -1
  297. package/web/.next/static/chunks/2s1d7_ca-qsif.js +1 -0
  298. package/web/.next/static/chunks/39m3_x0v7i-za.js +1 -0
  299. package/web/.next/static/chunks/{1zv4cn94bmk2x.js → 3_jnl679rr4gb.js} +1 -1
  300. package/web/.next/static/chunks/{3qmppgfbfoif6.js → 3ool2gtdd_dtc.js} +1 -1
  301. package/web/.next/static/chunks/3z9siyl43u-rb.js +1 -0
  302. package/web/.next/static/chunks/{3tmji77wyx7q4.js → 3zqj28w22cklq.js} +1 -1
  303. package/web/.next/trace +1 -1
  304. package/web/.next/trace-build +1 -1
  305. package/web/.next/server/chunks/ssr/_0239h2ocqyibp._.js +0 -3
  306. package/web/.next/server/chunks/ssr/_087cuueeby0hw._.js +0 -3
  307. package/web/.next/server/chunks/ssr/_1e7srghw1_x9p._.js +0 -57
  308. package/web/.next/server/chunks/ssr/_1e7srghw1_x9p._.js.map +0 -1
  309. package/web/.next/server/chunks/ssr/_1q0rhps0nvrq5._.js +0 -57
  310. package/web/.next/server/chunks/ssr/_1q0rhps0nvrq5._.js.map +0 -1
  311. package/web/.next/static/chunks/06tpbp-er8dog.js +0 -1
  312. package/web/.next/static/chunks/1ovt2ef2naqgj.js +0 -1
  313. package/web/.next/static/chunks/24qt7-p52g31c.js +0 -1
  314. package/web/.next/static/chunks/2ukdl2v0q677n.js +0 -1
  315. package/web/.next/static/chunks/33kxvt_kxg5yb.js +0 -1
  316. package/web/.next/static/chunks/38m6y148vwux3.js +0 -1
  317. /package/web/.next/static/{9KCcVgnuuZ1fElZoEqTjx → vYCXAc7TLc4U7-Vynu6VC}/_buildManifest.js +0 -0
  318. /package/web/.next/static/{9KCcVgnuuZ1fElZoEqTjx → vYCXAc7TLc4U7-Vynu6VC}/_clientMiddlewareManifest.js +0 -0
  319. /package/web/.next/static/{9KCcVgnuuZ1fElZoEqTjx → vYCXAc7TLc4U7-Vynu6VC}/_ssgManifest.js +0 -0
@@ -0,0 +1,65 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { ok } from '../shared/result.js';
3
+ const MINUTES_PER_DAY = 24 * 60;
4
+ const MS_PER_MINUTE = 60_000;
5
+ const isMinuteOfDay = (minute) => Number.isInteger(minute) && minute >= 0 && minute < MINUTES_PER_DAY;
6
+ function isKnownTimeZone(timeZone) {
7
+ try {
8
+ new Intl.DateTimeFormat('en-US', { timeZone });
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ /** A quiet window, refused when either end is not a minute of the day, both ends are one, or the time zone is unknown. */
16
+ export function quietWindowOf(window) {
17
+ const { fromMinute, toMinute, timeZone } = window;
18
+ if (!isMinuteOfDay(fromMinute) || !isMinuteOfDay(toMinute)) {
19
+ return refuse('INVALID_QUIET_HOURS', 'Quiet hours start and end at a time of the day');
20
+ }
21
+ if (fromMinute === toMinute) {
22
+ return refuse('INVALID_QUIET_HOURS', 'Quiet hours end at another time than they start');
23
+ }
24
+ if (!isKnownTimeZone(timeZone)) {
25
+ return refuse('INVALID_QUIET_HOURS', `No time zone is named ${timeZone}`);
26
+ }
27
+ return ok({ fromMinute, toMinute, timeZone });
28
+ }
29
+ function localTimeOf(instant, timeZone) {
30
+ const parts = new Intl.DateTimeFormat('en-US', { timeZone, hourCycle: 'h23', year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric' }).formatToParts(instant);
31
+ const part = (type) => Number(parts.find((each) => each.type === type)?.value);
32
+ const [year, month, day, hour, minute] = [part('year'), part('month'), part('day'), part('hour'), part('minute')];
33
+ return { year, month, day, minute: hour * 60 + minute, asUtcMs: Date.UTC(year, month - 1, day, hour, minute) };
34
+ }
35
+ /** How far the time zone's clock is ahead of UTC at the instant. */
36
+ function offsetMsAt(instantMs, timeZone) {
37
+ const floored = Math.floor(instantMs / MS_PER_MINUTE) * MS_PER_MINUTE;
38
+ return localTimeOf(new Date(floored), timeZone).asUtcMs - floored;
39
+ }
40
+ /** The instant the time zone's clock shows the minute on the day, the day counted from the local day given. */
41
+ function instantAt(local, { dayOffset, minute, timeZone }) {
42
+ const asUtcMs = Date.UTC(local.year, local.month - 1, local.day + dayOffset, 0, minute);
43
+ // The offset at a first guess, then at the instant it gives, so a change of the clocks in between is taken.
44
+ const guess = asUtcMs - offsetMsAt(asUtcMs, timeZone);
45
+ return new Date(asUtcMs - offsetMsAt(guess, timeZone));
46
+ }
47
+ /** The quiet hours in effect at the instant, or none while they are off or the instant is outside them. */
48
+ export function quietSpellAt(hours, now) {
49
+ if (!hours.isOn) {
50
+ return undefined;
51
+ }
52
+ const { fromMinute, toMinute, timeZone } = hours;
53
+ const local = localTimeOf(now, timeZone);
54
+ const isCrossingMidnight = fromMinute > toMinute;
55
+ const isAfterStart = local.minute >= fromMinute;
56
+ const isBeforeEnd = local.minute < toMinute;
57
+ if (isCrossingMidnight ? !isAfterStart && !isBeforeEnd : !isAfterStart || !isBeforeEnd) {
58
+ return undefined;
59
+ }
60
+ // Crossing midnight, a spell began yesterday when it is after midnight now, and ends tomorrow when it is before.
61
+ const startDay = isCrossingMidnight && !isAfterStart ? -1 : 0;
62
+ const endDay = isCrossingMidnight && isAfterStart ? 1 : 0;
63
+ return { since: instantAt(local, { dayOffset: startDay, minute: fromMinute, timeZone }), until: instantAt(local, { dayOffset: endDay, minute: toMinute, timeZone }) };
64
+ }
65
+ //# sourceMappingURL=quiet-hours.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quiet-hours.js","sourceRoot":"","sources":["../../../src/core/people/quiet-hours.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Quiet ships (preferences design): per fleet and person ship, the ships
3
+ * the person quieted. A quiet ship never wakes the person, through web push
4
+ * or email, for any job; Slack and a chat are places, not wakes, so their
5
+ * per job switches stand. Every item still waits whatever is chosen. A ship
6
+ * woken again is kept so, with when, as it wakes only for what it sends
7
+ * after. Kept by ship id, so a rename stays quiet and a reused name does
8
+ * not inherit it; the name is the one it had when quieted.
9
+ */
10
+ import type { FleetId, ShipId } from '@aeolus-fleet/common';
11
+ import type { PersonShip } from './ports.js';
12
+ import type { Routing } from './routing.js';
13
+ /** A ship a person quieted, or woke again, with when they did. */
14
+ export interface QuietShip {
15
+ readonly fleetId: FleetId;
16
+ readonly shipId: ShipId;
17
+ readonly quietShipId: ShipId;
18
+ readonly name: string;
19
+ readonly isQuiet: boolean;
20
+ readonly changedAt: Date;
21
+ }
22
+ /** A page of the person's quiet ships, the latest quieted first, and the cursor of the next; null on the last. */
23
+ export interface QuietShipsPage {
24
+ readonly ships: readonly QuietShip[];
25
+ readonly nextCursor: ShipId | null;
26
+ }
27
+ /** Outbound port: each person's quiet ships, by fleet and person ship. */
28
+ export interface QuietShips {
29
+ /** What the person chose for any of these ships: quiet, or woken again. */
30
+ among(ship: PersonShip, shipIds: readonly ShipId[]): Promise<QuietShip[]>;
31
+ /** The quiet ones only, the latest quieted first, after the cursor. */
32
+ listQuiet(ship: PersonShip, page: {
33
+ cursor: ShipId | null;
34
+ limit: number;
35
+ }): Promise<QuietShipsPage>;
36
+ /** Keeps it, or keeps it anew for its ship. */
37
+ save(quietShip: QuietShip): Promise<void>;
38
+ }
39
+ /** Routing with the person's quiet ships: none of them wakes, and one woken again wakes for what it sent since. */
40
+ export declare function withQuietShips(routing: Routing, quietShips: readonly QuietShip[]): Routing;
@@ -0,0 +1,24 @@
1
+ /** Whether the place wakes the person, so a quiet ship keeps out of it. */
2
+ function isWakePlace(place) {
3
+ switch (place) {
4
+ case 'web-push':
5
+ case 'email':
6
+ return true;
7
+ case 'slack':
8
+ case 'chat':
9
+ return false;
10
+ }
11
+ }
12
+ /** Routing with the person's quiet ships: none of them wakes, and one woken again wakes for what it sent since. */
13
+ export function withQuietShips(routing, quietShips) {
14
+ const chosen = new Map(quietShips.map((quietShip) => [quietShip.quietShipId, quietShip]));
15
+ const isQuietFor = ({ senderShipId, sentAt }) => {
16
+ const quietShip = chosen.get(senderShipId);
17
+ return quietShip !== undefined && (quietShip.isQuiet || sentAt.getTime() < quietShip.changedAt.getTime());
18
+ };
19
+ return {
20
+ isOn: (job, place) => routing.isOn(job, place),
21
+ isShowing: (place, item) => !(isWakePlace(place) && isQuietFor(item)) && routing.isShowing(place, item),
22
+ };
23
+ }
24
+ //# sourceMappingURL=quiet-ships.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quiet-ships.js","sourceRoot":"","sources":["../../../src/core/people/quiet-ships.ts"],"names":[],"mappings":"AAwCA,2EAA2E;AAC3E,SAAS,WAAW,CAAC,KAAmB;IACtC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,UAAU,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,IAAI,CAAC;QACd,KAAK,OAAO,CAAC;QACb,KAAK,MAAM;YACT,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,mHAAmH;AACnH,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,UAAgC;IAC/E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1F,MAAM,UAAU,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,EAAc,EAAW,EAAE;QACnE,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC3C,OAAO,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5G,CAAC,CAAC;IACF,OAAO;QACL,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC;QAC9C,SAAS,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC;KACxG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { DeliveryId } from '@aeolus-fleet/common';
2
+ import { type DomainError } from '../shared/errors.js';
3
+ import { type Result } from '../shared/result.js';
4
+ import type { CrewPersonShip } from './crew-person-ship.js';
5
+ import type { HeldDeliveries } from './held-deliveries.js';
6
+ import type { OpenedView } from './open-delivery.js';
7
+ import { type PersonCaller, type PersonCrewError } from './person-crew.js';
8
+ import type { OpenedDeliveries, PersonCrews, PersonShipDoor } from './ports.js';
9
+ type ReadItemError = PersonCrewError | DomainError<'NO_SUCH_DELIVERY'>;
10
+ export type ReadItem = (input: {
11
+ caller: PersonCaller;
12
+ deliveryId: DeliveryId;
13
+ }) => Promise<Result<OpenedView, ReadItemError>>;
14
+ interface ReadItemDeps {
15
+ crewPersonShip: CrewPersonShip;
16
+ crews: PersonCrews;
17
+ door: PersonShipDoor;
18
+ held: HeldDeliveries;
19
+ opened: Pick<OpenedDeliveries, 'list'>;
20
+ }
21
+ /**
22
+ * Use case: a person's client reads one item of their person ship whole by its
23
+ * delivery id, in any state, as opening gives it, and acknowledges nothing
24
+ * and keeps nothing. A waiting one is read from what waits, one they
25
+ * acknowledged and are not done with is read again from the fleet, and a
26
+ * done one is found in the ship's record, newest first. A delivery of
27
+ * another ship is none of these, so it is refused as no such delivery. A
28
+ * sealed message the fleet cannot unseal now is refused, as opening refuses it.
29
+ */
30
+ export declare function createReadItem(deps: ReadItemDeps): ReadItem;
31
+ export {};
@@ -0,0 +1,77 @@
1
+ import { refuse } from '../shared/errors.js';
2
+ import { ok } from '../shared/result.js';
3
+ import { inboxEntryOf } from './inbox-entry.js';
4
+ import { meetingNoticeSaid } from './meeting-notice.js';
5
+ import { asPersonCrew, KEY_UNAVAILABLE, SEALED_MESSAGE, withOwnRefusal } from './person-crew.js';
6
+ import { waitingFor } from './read-inbox.js';
7
+ import { RECORD_PAGE_SIZE } from './read-record.js';
8
+ import { askingOf, staleOf } from './stale-item.js';
9
+ /**
10
+ * Use case: a person's client reads one item of their person ship whole by its
11
+ * delivery id, in any state, as opening gives it, and acknowledges nothing
12
+ * and keeps nothing. A waiting one is read from what waits, one they
13
+ * acknowledged and are not done with is read again from the fleet, and a
14
+ * done one is found in the ship's record, newest first. A delivery of
15
+ * another ship is none of these, so it is refused as no such delivery. A
16
+ * sealed message the fleet cannot unseal now is refused, as opening refuses it.
17
+ */
18
+ export function createReadItem(deps) {
19
+ return async ({ caller, deliveryId }) => {
20
+ const waiting = await waitingFor(deps, caller);
21
+ if (!waiting.isOk) {
22
+ return waiting;
23
+ }
24
+ const { crew, deliveries } = waiting.value;
25
+ const delivery = deliveries.find((each) => each.deliveryId === deliveryId);
26
+ const found = delivery === undefined ? await readFromFleet(deps, { caller, deliveryId }) : ok(delivery);
27
+ if (!found.isOk) {
28
+ return found;
29
+ }
30
+ const stale = await staleFor(deps, { caller, crew, delivery: found.value, waiting: deliveries });
31
+ return ok({ ...inboxEntryOf(found.value), contentType: found.value.contentType, payload: found.value.payload, meetingId: found.value.meetingId, said: meetingNoticeSaid({ ...found.value, from: found.value.senderName }), stale });
32
+ };
33
+ }
34
+ /** An item that no more waits: the person acknowledged it and is not done, so the fleet reads it again, or it is done, so the record holds it. */
35
+ async function readFromFleet(deps, asked) {
36
+ const { caller, deliveryId } = asked;
37
+ const reread = await asPersonCrew(deps, { caller, run: (crew) => withOwnRefusal(deps.door.delivery(crew.crewToken, deliveryId)) });
38
+ if (!reread.isOk) {
39
+ return reread;
40
+ }
41
+ const delivery = reread.value.value;
42
+ if (delivery.isOk) {
43
+ return ok(delivery.value);
44
+ }
45
+ if (delivery.error.code === KEY_UNAVAILABLE) {
46
+ return refuse('KEY_UNAVAILABLE', SEALED_MESSAGE);
47
+ }
48
+ return inRecord(deps, asked);
49
+ }
50
+ /** Looks through the record, newest first, until the delivery or the ids older than it. */
51
+ async function inRecord(deps, asked) {
52
+ const { caller, deliveryId, cursor = null } = asked;
53
+ const read = await asPersonCrew(deps, { caller, run: (crew) => withOwnRefusal(deps.door.record(crew.crewToken, { cursor, limit: RECORD_PAGE_SIZE })) });
54
+ if (!read.isOk) {
55
+ return read;
56
+ }
57
+ const page = read.value.value;
58
+ if (!page.isOk) {
59
+ return refuse('FLEET_UNAVAILABLE', `The item cannot be read now: ${page.error.message}. Nothing is lost`);
60
+ }
61
+ const recorded = page.value.items.find((each) => each.deliveryId === deliveryId);
62
+ if (recorded !== undefined) {
63
+ return recorded.isPayloadUnreadable ? refuse('KEY_UNAVAILABLE', SEALED_MESSAGE) : ok(recorded);
64
+ }
65
+ const oldest = page.value.items.at(-1)?.deliveryId;
66
+ if (oldest === undefined || oldest < deliveryId || page.value.nextCursor === null) {
67
+ return refuse('NO_SUCH_DELIVERY', `No delivery ${deliveryId} of your person ship waits, is opened or is done: read your inbox again`);
68
+ }
69
+ return inRecord(deps, { ...asked, cursor: page.value.nextCursor });
70
+ }
71
+ /** Whether its asker withdrew or replaced the question or step it asks, among what waits and what the person opened; only told, never ended. */
72
+ async function staleFor(deps, look) {
73
+ const { caller, crew, delivery, waiting } = look;
74
+ const opened = await deps.opened.list(caller.fleetId, crew.shipId);
75
+ return staleOf(askingOf(delivery), [...waiting.map(askingOf), ...opened]);
76
+ }
77
+ //# sourceMappingURL=read-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-item.js","sourceRoot":"","sources":["../../../src/core/people/read-item.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ShipId } from '@aeolus-fleet/common';
2
+ import { type Result } from '../shared/result.js';
3
+ import type { CrewPersonShip } from './crew-person-ship.js';
4
+ import { type PersonCaller, type PersonCrewError } from './person-crew.js';
5
+ import type { QuietShips } from './quiet-ships.js';
6
+ import { type QuietShipView } from './read-quiet-ships.js';
7
+ export type ReadQuietAmong = (read: {
8
+ caller: PersonCaller;
9
+ shipIds: readonly ShipId[];
10
+ }) => Promise<Result<QuietShipView[], PersonCrewError>>;
11
+ /** Use case: a person's client asks which of the ships it shows are quiet (preferences design), to mark them in a conversation and the list of conversations. */
12
+ export declare function createReadQuietAmong(deps: {
13
+ crewPersonShip: CrewPersonShip;
14
+ quietShips: Pick<QuietShips, 'among'>;
15
+ }): ReadQuietAmong;
@@ -0,0 +1,15 @@
1
+ import { ok } from '../shared/result.js';
2
+ import { personCrewOf } from './person-crew.js';
3
+ import { quietShipViewOf } from './read-quiet-ships.js';
4
+ /** Use case: a person's client asks which of the ships it shows are quiet (preferences design), to mark them in a conversation and the list of conversations. */
5
+ export function createReadQuietAmong(deps) {
6
+ return async ({ caller, shipIds }) => {
7
+ const crew = await personCrewOf(deps.crewPersonShip, caller);
8
+ if (!crew.isOk) {
9
+ return crew;
10
+ }
11
+ const chosen = await deps.quietShips.among({ fleetId: caller.fleetId, shipId: crew.value.shipId }, shipIds);
12
+ return ok(chosen.filter(({ isQuiet }) => isQuiet).map(quietShipViewOf));
13
+ };
14
+ }
15
+ //# sourceMappingURL=read-quiet-among.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-quiet-among.js","sourceRoot":"","sources":["../../../src/core/people/read-quiet-among.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAA2C,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,eAAe,EAAsB,MAAM,uBAAuB,CAAC;AAI5E,iKAAiK;AACjK,MAAM,UAAU,oBAAoB,CAAC,IAA+E;IAClH,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;QAC5G,OAAO,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { Clock } from '../shared/clock.js';
2
+ import { type Result } from '../shared/result.js';
3
+ import type { CrewPersonShip } from './crew-person-ship.js';
4
+ import type { HeldDeliveries } from './held-deliveries.js';
5
+ import { type PersonCaller, type PersonCrewError } from './person-crew.js';
6
+ import type { PersonCrews, PersonShipDoor } from './ports.js';
7
+ import { type QuietHoursStore, type QuietSpell, type QuietWindow } from './quiet-hours.js';
8
+ /** A person's quiet hours as their client draws them: on or off, the window set, if any, and the spell in effect now with how many of what waits arrived since it began, if any. */
9
+ export interface QuietHoursView {
10
+ readonly isOn: boolean;
11
+ readonly window: QuietWindow | null;
12
+ readonly quietNow: (QuietSpell & {
13
+ readonly arrived: number;
14
+ }) | null;
15
+ }
16
+ export type ReadQuietHours = (caller: PersonCaller) => Promise<Result<QuietHoursView, PersonCrewError>>;
17
+ /**
18
+ * Use case: a person's client reads their quiet hours (preferences design);
19
+ * off with no window while they set none. While they are in effect, it
20
+ * counts what waits that arrived since they began, from what waits as the
21
+ * inbox reads it; outside them it asks the fleet nothing.
22
+ */
23
+ export declare function createReadQuietHours(deps: {
24
+ crewPersonShip: CrewPersonShip;
25
+ crews: PersonCrews;
26
+ door: PersonShipDoor;
27
+ held: HeldDeliveries;
28
+ quietHours: Pick<QuietHoursStore, 'find'>;
29
+ clock: Clock;
30
+ }): ReadQuietHours;
@@ -0,0 +1,35 @@
1
+ import { ok } from '../shared/result.js';
2
+ import { personCrewOf } from './person-crew.js';
3
+ import { quietSpellAt } from './quiet-hours.js';
4
+ import { waitingFor } from './read-inbox.js';
5
+ /**
6
+ * Use case: a person's client reads their quiet hours (preferences design);
7
+ * off with no window while they set none. While they are in effect, it
8
+ * counts what waits that arrived since they began, from what waits as the
9
+ * inbox reads it; outside them it asks the fleet nothing.
10
+ */
11
+ export function createReadQuietHours(deps) {
12
+ return async (caller) => {
13
+ const crew = await personCrewOf(deps.crewPersonShip, caller);
14
+ if (!crew.isOk) {
15
+ return crew;
16
+ }
17
+ const hours = await deps.quietHours.find({ fleetId: caller.fleetId, shipId: crew.value.shipId });
18
+ if (hours === undefined) {
19
+ return ok({ isOn: false, window: null, quietNow: null });
20
+ }
21
+ const { isOn, fromMinute, toMinute, timeZone } = hours;
22
+ const window = { fromMinute, toMinute, timeZone };
23
+ const spell = quietSpellAt(hours, deps.clock.now());
24
+ if (spell === undefined) {
25
+ return ok({ isOn, window, quietNow: null });
26
+ }
27
+ const waiting = await waitingFor(deps, caller);
28
+ if (!waiting.isOk) {
29
+ return waiting;
30
+ }
31
+ const arrived = waiting.value.deliveries.filter(({ sentAt }) => sentAt.getTime() >= spell.since.getTime()).length;
32
+ return ok({ isOn, window, quietNow: { ...spell, arrived } });
33
+ };
34
+ }
35
+ //# sourceMappingURL=read-quiet-hours.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-quiet-hours.js","sourceRoot":"","sources":["../../../src/core/people/read-quiet-hours.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAA2C,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,YAAY,EAA2D,MAAM,kBAAkB,CAAC;AACzG,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAW7C;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAiK;IACpM,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACjG,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QACvD,MAAM,MAAM,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACpD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAClH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ShipId } from '@aeolus-fleet/common';
2
+ import { type Result } from '../shared/result.js';
3
+ import type { CrewPersonShip } from './crew-person-ship.js';
4
+ import { type PersonCaller, type PersonCrewError } from './person-crew.js';
5
+ import type { QuietShip, QuietShips } from './quiet-ships.js';
6
+ /** How many quiet ships a page holds, as preferences show them. */
7
+ export declare const QUIET_SHIPS_PAGE_SIZE = 20;
8
+ /** A quiet ship as a person's client shows it: its name when quieted, and since when. */
9
+ export interface QuietShipView {
10
+ readonly shipId: ShipId;
11
+ readonly name: string;
12
+ readonly since: Date;
13
+ }
14
+ export declare function quietShipViewOf({ quietShipId, name, changedAt }: QuietShip): QuietShipView;
15
+ export type ReadQuietShips = (read: {
16
+ caller: PersonCaller;
17
+ cursor: ShipId | null;
18
+ }) => Promise<Result<{
19
+ ships: QuietShipView[];
20
+ nextCursor: ShipId | null;
21
+ }, PersonCrewError>>;
22
+ /** Use case: a person's client lists their quiet ships (preferences design), 20 at a time, the latest quieted first, after the cursor the last page answered. */
23
+ export declare function createReadQuietShips(deps: {
24
+ crewPersonShip: CrewPersonShip;
25
+ quietShips: Pick<QuietShips, 'listQuiet'>;
26
+ }): ReadQuietShips;
@@ -0,0 +1,19 @@
1
+ import { ok } from '../shared/result.js';
2
+ import { personCrewOf } from './person-crew.js';
3
+ /** How many quiet ships a page holds, as preferences show them. */
4
+ export const QUIET_SHIPS_PAGE_SIZE = 20;
5
+ export function quietShipViewOf({ quietShipId, name, changedAt }) {
6
+ return { shipId: quietShipId, name, since: changedAt };
7
+ }
8
+ /** Use case: a person's client lists their quiet ships (preferences design), 20 at a time, the latest quieted first, after the cursor the last page answered. */
9
+ export function createReadQuietShips(deps) {
10
+ return async ({ caller, cursor }) => {
11
+ const crew = await personCrewOf(deps.crewPersonShip, caller);
12
+ if (!crew.isOk) {
13
+ return crew;
14
+ }
15
+ const page = await deps.quietShips.listQuiet({ fleetId: caller.fleetId, shipId: crew.value.shipId }, { cursor, limit: QUIET_SHIPS_PAGE_SIZE });
16
+ return ok({ ships: page.ships.map(quietShipViewOf), nextCursor: page.nextCursor });
17
+ };
18
+ }
19
+ //# sourceMappingURL=read-quiet-ships.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-quiet-ships.js","sourceRoot":"","sources":["../../../src/core/people/read-quiet-ships.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAA2C,MAAM,kBAAkB,CAAC;AAGzF,mEAAmE;AACnE,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AASxC,MAAM,UAAU,eAAe,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAa;IACzE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AACzD,CAAC;AAID,iKAAiK;AACjK,MAAM,UAAU,oBAAoB,CAAC,IAAmF;IACtH,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC/I,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACrF,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Clock } from '../shared/clock.js';
2
+ import type { DomainError } from '../shared/errors.js';
3
+ import { type Result } from '../shared/result.js';
4
+ import type { CrewPersonShip } from './crew-person-ship.js';
5
+ import { type PersonCaller, type PersonCrewError } from './person-crew.js';
6
+ import { type QuietHoursStore, type QuietWindow } from './quiet-hours.js';
7
+ export type SetQuietHours = (set: {
8
+ caller: PersonCaller;
9
+ isOn: boolean;
10
+ } & QuietWindow) => Promise<Result<undefined, PersonCrewError | DomainError<'INVALID_QUIET_HOURS'>>>;
11
+ /**
12
+ * Use case: a person sets their quiet hours (preferences design), on or off
13
+ * with their window, kept by fleet and person ship with when they set them.
14
+ * It applies at once, as every wake reads them anew. A window that is not
15
+ * one is refused, keeping nothing.
16
+ */
17
+ export declare function createSetQuietHours(deps: {
18
+ crewPersonShip: CrewPersonShip;
19
+ quietHours: Pick<QuietHoursStore, 'save'>;
20
+ clock: Clock;
21
+ }): SetQuietHours;
@@ -0,0 +1,24 @@
1
+ import { ok } from '../shared/result.js';
2
+ import { personCrewOf } from './person-crew.js';
3
+ import { quietWindowOf } from './quiet-hours.js';
4
+ /**
5
+ * Use case: a person sets their quiet hours (preferences design), on or off
6
+ * with their window, kept by fleet and person ship with when they set them.
7
+ * It applies at once, as every wake reads them anew. A window that is not
8
+ * one is refused, keeping nothing.
9
+ */
10
+ export function createSetQuietHours(deps) {
11
+ return async ({ caller, isOn, ...asked }) => {
12
+ const window = quietWindowOf(asked);
13
+ if (!window.isOk) {
14
+ return window;
15
+ }
16
+ const crew = await personCrewOf(deps.crewPersonShip, caller);
17
+ if (!crew.isOk) {
18
+ return crew;
19
+ }
20
+ await deps.quietHours.save({ fleetId: caller.fleetId, shipId: crew.value.shipId, isOn, ...window.value, changedAt: deps.clock.now() });
21
+ return ok(undefined);
22
+ };
23
+ }
24
+ //# sourceMappingURL=set-quiet-hours.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-quiet-hours.js","sourceRoot":"","sources":["../../../src/core/people/set-quiet-hours.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAA2C,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,aAAa,EAA0C,MAAM,kBAAkB,CAAC;AAIzF;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAiG;IACnI,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvI,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { ShipId } from '@aeolus-fleet/common';
2
+ import type { Clock } from '../shared/clock.js';
3
+ import { type Result } from '../shared/result.js';
4
+ import type { CrewPersonShip } from './crew-person-ship.js';
5
+ import { type PersonCaller, type PersonCrewError } from './person-crew.js';
6
+ import type { QuietShips } from './quiet-ships.js';
7
+ export type TurnShipQuiet = (turn: {
8
+ caller: PersonCaller;
9
+ shipId: ShipId;
10
+ name: string;
11
+ isQuiet: boolean;
12
+ }) => Promise<Result<undefined, PersonCrewError>>;
13
+ /**
14
+ * Use case: a person quiets a ship, so it never wakes them, or wakes it
15
+ * again (preferences design), kept by fleet, person ship and ship with when.
16
+ * It applies at once, as every wake reads it anew. A ship already as asked
17
+ * is kept as it is, so a quiet ship keeps since when it was quieted; a ship
18
+ * never quieted needs nothing kept to wake the person.
19
+ */
20
+ export declare function createTurnShipQuiet(deps: {
21
+ crewPersonShip: CrewPersonShip;
22
+ quietShips: Pick<QuietShips, 'among' | 'save'>;
23
+ clock: Clock;
24
+ }): TurnShipQuiet;
@@ -0,0 +1,25 @@
1
+ import { ok } from '../shared/result.js';
2
+ import { personCrewOf } from './person-crew.js';
3
+ /**
4
+ * Use case: a person quiets a ship, so it never wakes them, or wakes it
5
+ * again (preferences design), kept by fleet, person ship and ship with when.
6
+ * It applies at once, as every wake reads it anew. A ship already as asked
7
+ * is kept as it is, so a quiet ship keeps since when it was quieted; a ship
8
+ * never quieted needs nothing kept to wake the person.
9
+ */
10
+ export function createTurnShipQuiet(deps) {
11
+ return async ({ caller, shipId, name, isQuiet }) => {
12
+ const crew = await personCrewOf(deps.crewPersonShip, caller);
13
+ if (!crew.isOk) {
14
+ return crew;
15
+ }
16
+ const ship = { fleetId: caller.fleetId, shipId: crew.value.shipId };
17
+ const [chosen] = await deps.quietShips.among(ship, [shipId]);
18
+ if ((chosen?.isQuiet ?? false) === isQuiet) {
19
+ return ok(undefined);
20
+ }
21
+ await deps.quietShips.save({ ...ship, quietShipId: shipId, name, isQuiet, changedAt: deps.clock.now() });
22
+ return ok(undefined);
23
+ };
24
+ }
25
+ //# sourceMappingURL=turn-ship-quiet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-ship-quiet.js","sourceRoot":"","sources":["../../../src/core/people/turn-ship-quiet.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,YAAY,EAA2C,MAAM,kBAAkB,CAAC;AAKzF;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAsG;IACxI,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,KAAK,CAAC,KAAK,OAAO,EAAE,CAAC;YAC3C,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;QACD,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACzG,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC"}
@@ -2,6 +2,8 @@ import type { ConnectionStore, FleetRefusal } from "../connection/ports.js";
2
2
  import type { Clock } from "../shared/clock.js";
3
3
  import { type Result } from "../shared/result.js";
4
4
  import type { RoutingDefaults, Routes } from "./routing.js";
5
+ import { type QuietHoursStore } from "./quiet-hours.js";
6
+ import { type QuietShips } from "./quiet-ships.js";
5
7
  import type { FocusedPages, PersonShip, PersonShipDoor, ShownElsewhere, WakeChannel, WakeChannelName, WakesSent } from "./ports.js";
6
8
  /**
7
9
  * What a wake came to: nothing left to wake (settled), a wake held back
@@ -43,7 +45,11 @@ export type WakePerson = (ship: PersonShip, crewToken: string) => Promise<Result
43
45
  * person routed there, even while a page is in focus; nothing wakes for those
44
46
  * (gateway scopes 9.5 step 5). It is asked at every wake, fresh deliveries
45
47
  * or none, so what it left unfinished is finished, and while anything is
46
- * left the wake counts as failed, so it is tried again.
48
+ * left the wake counts as failed, so it is tried again. The person's
49
+ * preferences are read anew at every wake too: a quiet ship's deliveries
50
+ * wake nobody and wait unhanded, and during quiet hours no wake goes out;
51
+ * the wake is held back until they end or a channel's window passes,
52
+ * whichever comes first, so turning them off applies by the next window.
47
53
  */
48
54
  export declare function createWakePerson(deps: {
49
55
  door: Pick<PersonShipDoor, "pushReceive" | "handed">;
@@ -55,6 +61,9 @@ export declare function createWakePerson(deps: {
55
61
  /** Where each person routed each job (Bridge, section 8), and the defaults where they chose nothing. */
56
62
  routes: Routes;
57
63
  defaults: RoutingDefaults;
64
+ /** The person's quiet hours and quiet ships (preferences design). */
65
+ quietHours: Pick<QuietHoursStore, "find">;
66
+ quietShips: Pick<QuietShips, "among">;
58
67
  wakesSent: WakesSent;
59
68
  focused: FocusedPages;
60
69
  /** How long a page counts in focus since it was last seen so. */
@@ -1,6 +1,8 @@
1
1
  import { RECEIVE_MAX_UPPER_BOUND } from "@aeolus-fleet/common";
2
2
  import { err, ok } from "../shared/result.js";
3
3
  import { ownStepsInBridgeOnly, routingOf } from "./routing.js";
4
+ import { quietSpellAt } from "./quiet-hours.js";
5
+ import { withQuietShips } from "./quiet-ships.js";
4
6
  /**
5
7
  * Use case: wakes a person for what waits on their person ship (wake a
6
8
  * person, W3, W8). It takes the ship's deliveries with the gateway as their
@@ -27,7 +29,11 @@ import { ownStepsInBridgeOnly, routingOf } from "./routing.js";
27
29
  * person routed there, even while a page is in focus; nothing wakes for those
28
30
  * (gateway scopes 9.5 step 5). It is asked at every wake, fresh deliveries
29
31
  * or none, so what it left unfinished is finished, and while anything is
30
- * left the wake counts as failed, so it is tried again.
32
+ * left the wake counts as failed, so it is tried again. The person's
33
+ * preferences are read anew at every wake too: a quiet ship's deliveries
34
+ * wake nobody and wait unhanded, and during quiet hours no wake goes out;
35
+ * the wake is held back until they end or a channel's window passes,
36
+ * whichever comes first, so turning them off applies by the next window.
31
37
  */
32
38
  export function createWakePerson(deps) {
33
39
  /** Channels that refused for good during an attempt still failing, by person ship: a retry of that attempt does not ask them again. */
@@ -87,7 +93,11 @@ export function createWakePerson(deps) {
87
93
  const refused = await handEach(allFresh, "page");
88
94
  return refused === undefined ? ok({ kind: "settled" }) : err(refused);
89
95
  }
90
- const showsOf = (channel) => (delivery) => routing.isShowing(channel.name, delivery);
96
+ const senderShipIds = [...new Set(allFresh.map(({ senderShipId }) => senderShipId))];
97
+ const [quietShips, quietHours] = await Promise.all([deps.quietShips.among(ship, senderShipIds), deps.quietHours.find(ship)]);
98
+ // A quiet ship wakes nobody: what it sent waits unhanded.
99
+ const wakeRouting = withQuietShips(routing, quietShips);
100
+ const showsOf = (channel) => (delivery) => wakeRouting.isShowing(channel.name, delivery);
91
101
  const turnedOn = (await Promise.all(deps.channels.map(async (channel) => allFresh.some(showsOf(channel)) && (await channel.isOn(ship)) ? [channel] : []))).flat();
92
102
  if (turnedOn.length === 0) {
93
103
  return ok({ kind: "settled" });
@@ -120,6 +130,12 @@ export function createWakePerson(deps) {
120
130
  if (fresh.length === 0) {
121
131
  return ok({ kind: "settled" });
122
132
  }
133
+ const quiet = quietHours === undefined ? undefined : quietSpellAt(quietHours, now);
134
+ if (quiet !== undefined) {
135
+ // Looked at again once a window passes, so quiet hours turned off meanwhile wake by then.
136
+ const nextWindowMs = Math.min(...turnedOn.filter((channel) => fresh.some(showsOf(channel))).map(({ windowMs }) => windowMs));
137
+ return ok({ kind: "inWindow", until: new Date(Math.min(quiet.until.getTime(), now.getTime() + nextWindowMs)) });
138
+ }
123
139
  const refusedBefore = refusedInAttempt.get(attemptKey(ship)) ?? new Set();
124
140
  /** The channels still asked that show any of these deliveries, with their windows. */
125
141
  const askedFor = (deliveries) => windows.filter(({ channel }) => !refusedBefore.has(channel.name) && deliveries.some(showsOf(channel)));