@heojeongbo/wirestage 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (489) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSES.md +21 -0
  3. package/README.md +150 -2
  4. package/dist/app/playwright/index.d.ts +3 -0
  5. package/dist/app/playwright/index.d.ts.map +1 -0
  6. package/dist/app/playwright/index.js +2 -0
  7. package/dist/app/playwright/index.js.map +1 -0
  8. package/dist/app/playwright/lib/fixture.d.ts +61 -0
  9. package/dist/app/playwright/lib/fixture.d.ts.map +1 -0
  10. package/dist/app/playwright/lib/fixture.js +110 -0
  11. package/dist/app/playwright/lib/fixture.js.map +1 -0
  12. package/dist/connect.d.ts +7 -0
  13. package/dist/connect.d.ts.map +1 -0
  14. package/dist/connect.js +7 -0
  15. package/dist/connect.js.map +1 -0
  16. package/dist/entities/frame/@x/plugin.d.ts +9 -0
  17. package/dist/entities/frame/@x/plugin.d.ts.map +1 -0
  18. package/dist/entities/frame/@x/plugin.js +2 -0
  19. package/dist/entities/frame/@x/plugin.js.map +1 -0
  20. package/dist/entities/frame/index.d.ts +6 -0
  21. package/dist/entities/frame/index.d.ts.map +1 -0
  22. package/dist/entities/frame/index.js +4 -0
  23. package/dist/entities/frame/index.js.map +1 -0
  24. package/dist/entities/frame/lib/filter.d.ts +8 -0
  25. package/dist/entities/frame/lib/filter.d.ts.map +1 -0
  26. package/dist/entities/frame/lib/filter.js +62 -0
  27. package/dist/entities/frame/lib/filter.js.map +1 -0
  28. package/dist/entities/frame/lib/payload.d.ts +8 -0
  29. package/dist/entities/frame/lib/payload.d.ts.map +1 -0
  30. package/dist/entities/frame/lib/payload.js +42 -0
  31. package/dist/entities/frame/lib/payload.js.map +1 -0
  32. package/dist/entities/frame/lib/snapshot.d.ts +15 -0
  33. package/dist/entities/frame/lib/snapshot.d.ts.map +1 -0
  34. package/dist/entities/frame/lib/snapshot.js +90 -0
  35. package/dist/entities/frame/lib/snapshot.js.map +1 -0
  36. package/dist/entities/frame/lib/timeline.d.ts +23 -0
  37. package/dist/entities/frame/lib/timeline.d.ts.map +1 -0
  38. package/dist/entities/frame/lib/timeline.js +122 -0
  39. package/dist/entities/frame/lib/timeline.js.map +1 -0
  40. package/dist/entities/frame/model/frame.d.ts +182 -0
  41. package/dist/entities/frame/model/frame.d.ts.map +1 -0
  42. package/dist/entities/frame/model/frame.js +2 -0
  43. package/dist/entities/frame/model/frame.js.map +1 -0
  44. package/dist/entities/plugin/index.d.ts +9 -0
  45. package/dist/entities/plugin/index.d.ts.map +1 -0
  46. package/dist/entities/plugin/index.js +3 -0
  47. package/dist/entities/plugin/index.js.map +1 -0
  48. package/dist/entities/plugin/lib/define-plugin.d.ts +8 -0
  49. package/dist/entities/plugin/lib/define-plugin.d.ts.map +1 -0
  50. package/dist/entities/plugin/lib/define-plugin.js +9 -0
  51. package/dist/entities/plugin/lib/define-plugin.js.map +1 -0
  52. package/dist/entities/plugin/lib/named.d.ts +10 -0
  53. package/dist/entities/plugin/lib/named.d.ts.map +1 -0
  54. package/dist/entities/plugin/lib/named.js +17 -0
  55. package/dist/entities/plugin/lib/named.js.map +1 -0
  56. package/dist/entities/plugin/model/attachment.d.ts +18 -0
  57. package/dist/entities/plugin/model/attachment.d.ts.map +1 -0
  58. package/dist/entities/plugin/model/attachment.js +2 -0
  59. package/dist/entities/plugin/model/attachment.js.map +1 -0
  60. package/dist/entities/plugin/model/http.d.ts +126 -0
  61. package/dist/entities/plugin/model/http.d.ts.map +1 -0
  62. package/dist/entities/plugin/model/http.js +2 -0
  63. package/dist/entities/plugin/model/http.js.map +1 -0
  64. package/dist/entities/plugin/model/page.d.ts +100 -0
  65. package/dist/entities/plugin/model/page.d.ts.map +1 -0
  66. package/dist/entities/plugin/model/page.js +2 -0
  67. package/dist/entities/plugin/model/page.js.map +1 -0
  68. package/dist/entities/plugin/model/plugin.d.ts +83 -0
  69. package/dist/entities/plugin/model/plugin.d.ts.map +1 -0
  70. package/dist/entities/plugin/model/plugin.js +2 -0
  71. package/dist/entities/plugin/model/plugin.js.map +1 -0
  72. package/dist/entities/plugin/model/socket.d.ts +102 -0
  73. package/dist/entities/plugin/model/socket.d.ts.map +1 -0
  74. package/dist/entities/plugin/model/socket.js +2 -0
  75. package/dist/entities/plugin/model/socket.js.map +1 -0
  76. package/dist/entities/plugin/model/stream.d.ts +43 -0
  77. package/dist/entities/plugin/model/stream.d.ts.map +1 -0
  78. package/dist/entities/plugin/model/stream.js +2 -0
  79. package/dist/entities/plugin/model/stream.js.map +1 -0
  80. package/dist/features/connect/index.d.ts +5 -0
  81. package/dist/features/connect/index.d.ts.map +1 -0
  82. package/dist/features/connect/index.js +4 -0
  83. package/dist/features/connect/index.js.map +1 -0
  84. package/dist/features/connect/lib/calls.d.ts +9 -0
  85. package/dist/features/connect/lib/calls.d.ts.map +1 -0
  86. package/dist/features/connect/lib/calls.js +46 -0
  87. package/dist/features/connect/lib/calls.js.map +1 -0
  88. package/dist/features/connect/lib/client.d.ts +33 -0
  89. package/dist/features/connect/lib/client.d.ts.map +1 -0
  90. package/dist/features/connect/lib/client.js +147 -0
  91. package/dist/features/connect/lib/client.js.map +1 -0
  92. package/dist/features/connect/lib/create-connect.d.ts +14 -0
  93. package/dist/features/connect/lib/create-connect.d.ts.map +1 -0
  94. package/dist/features/connect/lib/create-connect.js +124 -0
  95. package/dist/features/connect/lib/create-connect.js.map +1 -0
  96. package/dist/features/connect/lib/faults.d.ts +18 -0
  97. package/dist/features/connect/lib/faults.d.ts.map +1 -0
  98. package/dist/features/connect/lib/faults.js +85 -0
  99. package/dist/features/connect/lib/faults.js.map +1 -0
  100. package/dist/features/connect/lib/protocol.d.ts +42 -0
  101. package/dist/features/connect/lib/protocol.d.ts.map +1 -0
  102. package/dist/features/connect/lib/protocol.js +228 -0
  103. package/dist/features/connect/lib/protocol.js.map +1 -0
  104. package/dist/features/connect/lib/record.d.ts +14 -0
  105. package/dist/features/connect/lib/record.d.ts.map +1 -0
  106. package/dist/features/connect/lib/record.js +36 -0
  107. package/dist/features/connect/lib/record.js.map +1 -0
  108. package/dist/features/connect/lib/recorder.d.ts +77 -0
  109. package/dist/features/connect/lib/recorder.d.ts.map +1 -0
  110. package/dist/features/connect/lib/recorder.js +209 -0
  111. package/dist/features/connect/lib/recorder.js.map +1 -0
  112. package/dist/features/connect/lib/rules.d.ts +51 -0
  113. package/dist/features/connect/lib/rules.d.ts.map +1 -0
  114. package/dist/features/connect/lib/rules.js +222 -0
  115. package/dist/features/connect/lib/rules.js.map +1 -0
  116. package/dist/features/connect/lib/serve.d.ts +10 -0
  117. package/dist/features/connect/lib/serve.d.ts.map +1 -0
  118. package/dist/features/connect/lib/serve.js +78 -0
  119. package/dist/features/connect/lib/serve.js.map +1 -0
  120. package/dist/features/connect/lib/status-of.d.ts +11 -0
  121. package/dist/features/connect/lib/status-of.d.ts.map +1 -0
  122. package/dist/features/connect/lib/status-of.js +22 -0
  123. package/dist/features/connect/lib/status-of.js.map +1 -0
  124. package/dist/features/connect/lib/stubs.d.ts +18 -0
  125. package/dist/features/connect/lib/stubs.d.ts.map +1 -0
  126. package/dist/features/connect/lib/stubs.js +174 -0
  127. package/dist/features/connect/lib/stubs.js.map +1 -0
  128. package/dist/features/connect/lib/universal.d.ts +19 -0
  129. package/dist/features/connect/lib/universal.d.ts.map +1 -0
  130. package/dist/features/connect/lib/universal.js +71 -0
  131. package/dist/features/connect/lib/universal.js.map +1 -0
  132. package/dist/features/connect/model/types.d.ts +247 -0
  133. package/dist/features/connect/model/types.d.ts.map +1 -0
  134. package/dist/features/connect/model/types.js +2 -0
  135. package/dist/features/connect/model/types.js.map +1 -0
  136. package/dist/features/rest/index.d.ts +5 -0
  137. package/dist/features/rest/index.d.ts.map +1 -0
  138. package/dist/features/rest/index.js +3 -0
  139. package/dist/features/rest/index.js.map +1 -0
  140. package/dist/features/rest/lib/calls.d.ts +8 -0
  141. package/dist/features/rest/lib/calls.d.ts.map +1 -0
  142. package/dist/features/rest/lib/calls.js +32 -0
  143. package/dist/features/rest/lib/calls.js.map +1 -0
  144. package/dist/features/rest/lib/create-rest.d.ts +8 -0
  145. package/dist/features/rest/lib/create-rest.d.ts.map +1 -0
  146. package/dist/features/rest/lib/create-rest.js +136 -0
  147. package/dist/features/rest/lib/create-rest.js.map +1 -0
  148. package/dist/features/rest/lib/path.d.ts +14 -0
  149. package/dist/features/rest/lib/path.d.ts.map +1 -0
  150. package/dist/features/rest/lib/path.js +58 -0
  151. package/dist/features/rest/lib/path.js.map +1 -0
  152. package/dist/features/rest/lib/reply.d.ts +25 -0
  153. package/dist/features/rest/lib/reply.d.ts.map +1 -0
  154. package/dist/features/rest/lib/reply.js +40 -0
  155. package/dist/features/rest/lib/reply.js.map +1 -0
  156. package/dist/features/rest/model/types.d.ts +74 -0
  157. package/dist/features/rest/model/types.d.ts.map +1 -0
  158. package/dist/features/rest/model/types.js +2 -0
  159. package/dist/features/rest/model/types.js.map +1 -0
  160. package/dist/features/sse/index.d.ts +4 -0
  161. package/dist/features/sse/index.d.ts.map +1 -0
  162. package/dist/features/sse/index.js +3 -0
  163. package/dist/features/sse/index.js.map +1 -0
  164. package/dist/features/sse/lib/create-sse.d.ts +9 -0
  165. package/dist/features/sse/lib/create-sse.d.ts.map +1 -0
  166. package/dist/features/sse/lib/create-sse.js +120 -0
  167. package/dist/features/sse/lib/create-sse.js.map +1 -0
  168. package/dist/features/sse/lib/encode.d.ts +8 -0
  169. package/dist/features/sse/lib/encode.d.ts.map +1 -0
  170. package/dist/features/sse/lib/encode.js +29 -0
  171. package/dist/features/sse/lib/encode.js.map +1 -0
  172. package/dist/features/sse/model/types.d.ts +62 -0
  173. package/dist/features/sse/model/types.d.ts.map +1 -0
  174. package/dist/features/sse/model/types.js +2 -0
  175. package/dist/features/sse/model/types.js.map +1 -0
  176. package/dist/features/webrtc/index.d.ts +3 -0
  177. package/dist/features/webrtc/index.d.ts.map +1 -0
  178. package/dist/features/webrtc/index.js +2 -0
  179. package/dist/features/webrtc/index.js.map +1 -0
  180. package/dist/features/webrtc/lib/create-webrtc.d.ts +9 -0
  181. package/dist/features/webrtc/lib/create-webrtc.d.ts.map +1 -0
  182. package/dist/features/webrtc/lib/create-webrtc.js +123 -0
  183. package/dist/features/webrtc/lib/create-webrtc.js.map +1 -0
  184. package/dist/features/webrtc/lib/rtc-page-module.d.ts +22 -0
  185. package/dist/features/webrtc/lib/rtc-page-module.d.ts.map +1 -0
  186. package/dist/features/webrtc/lib/rtc-page-module.js +161 -0
  187. package/dist/features/webrtc/lib/rtc-page-module.js.map +1 -0
  188. package/dist/features/webrtc/lib/to-frame.d.ts +9 -0
  189. package/dist/features/webrtc/lib/to-frame.d.ts.map +1 -0
  190. package/dist/features/webrtc/lib/to-frame.js +43 -0
  191. package/dist/features/webrtc/lib/to-frame.js.map +1 -0
  192. package/dist/features/webrtc/model/types.d.ts +70 -0
  193. package/dist/features/webrtc/model/types.d.ts.map +1 -0
  194. package/dist/features/webrtc/model/types.js +2 -0
  195. package/dist/features/webrtc/model/types.js.map +1 -0
  196. package/dist/features/websocket/index.d.ts +3 -0
  197. package/dist/features/websocket/index.d.ts.map +1 -0
  198. package/dist/features/websocket/index.js +2 -0
  199. package/dist/features/websocket/index.js.map +1 -0
  200. package/dist/features/websocket/lib/create-websocket.d.ts +9 -0
  201. package/dist/features/websocket/lib/create-websocket.d.ts.map +1 -0
  202. package/dist/features/websocket/lib/create-websocket.js +34 -0
  203. package/dist/features/websocket/lib/create-websocket.js.map +1 -0
  204. package/dist/features/websocket/lib/mock.d.ts +6 -0
  205. package/dist/features/websocket/lib/mock.d.ts.map +1 -0
  206. package/dist/features/websocket/lib/mock.js +96 -0
  207. package/dist/features/websocket/lib/mock.js.map +1 -0
  208. package/dist/features/websocket/lib/proxy.d.ts +9 -0
  209. package/dist/features/websocket/lib/proxy.d.ts.map +1 -0
  210. package/dist/features/websocket/lib/proxy.js +107 -0
  211. package/dist/features/websocket/lib/proxy.js.map +1 -0
  212. package/dist/features/websocket/lib/wire.d.ts +16 -0
  213. package/dist/features/websocket/lib/wire.d.ts.map +1 -0
  214. package/dist/features/websocket/lib/wire.js +46 -0
  215. package/dist/features/websocket/lib/wire.js.map +1 -0
  216. package/dist/features/websocket/model/types.d.ts +129 -0
  217. package/dist/features/websocket/model/types.d.ts.map +1 -0
  218. package/dist/features/websocket/model/types.js +2 -0
  219. package/dist/features/websocket/model/types.js.map +1 -0
  220. package/dist/index.d.ts +27 -0
  221. package/dist/index.d.ts.map +1 -0
  222. package/dist/index.js +16 -0
  223. package/dist/index.js.map +1 -0
  224. package/dist/playwright.d.ts +4 -0
  225. package/dist/playwright.d.ts.map +1 -0
  226. package/dist/playwright.js +2 -0
  227. package/dist/playwright.js.map +1 -0
  228. package/dist/rest.d.ts +3 -0
  229. package/dist/rest.d.ts.map +1 -0
  230. package/dist/rest.js +3 -0
  231. package/dist/rest.js.map +1 -0
  232. package/dist/shared/api/http-server/index.d.ts +3 -0
  233. package/dist/shared/api/http-server/index.d.ts.map +1 -0
  234. package/dist/shared/api/http-server/index.js +2 -0
  235. package/dist/shared/api/http-server/index.js.map +1 -0
  236. package/dist/shared/api/http-server/listen.d.ts +25 -0
  237. package/dist/shared/api/http-server/listen.d.ts.map +1 -0
  238. package/dist/shared/api/http-server/listen.js +44 -0
  239. package/dist/shared/api/http-server/listen.js.map +1 -0
  240. package/dist/shared/api/playwright/index.d.ts +2 -0
  241. package/dist/shared/api/playwright/index.d.ts.map +1 -0
  242. package/dist/shared/api/playwright/index.js +2 -0
  243. package/dist/shared/api/playwright/index.js.map +1 -0
  244. package/dist/shared/api/playwright/ports.d.ts +117 -0
  245. package/dist/shared/api/playwright/ports.d.ts.map +1 -0
  246. package/dist/shared/api/playwright/ports.js +11 -0
  247. package/dist/shared/api/playwright/ports.js.map +1 -0
  248. package/dist/shared/api/stream-server/index.d.ts +3 -0
  249. package/dist/shared/api/stream-server/index.d.ts.map +1 -0
  250. package/dist/shared/api/stream-server/index.js +2 -0
  251. package/dist/shared/api/stream-server/index.js.map +1 -0
  252. package/dist/shared/api/stream-server/stream-server.d.ts +43 -0
  253. package/dist/shared/api/stream-server/stream-server.d.ts.map +1 -0
  254. package/dist/shared/api/stream-server/stream-server.js +160 -0
  255. package/dist/shared/api/stream-server/stream-server.js.map +1 -0
  256. package/dist/shared/lib/async/arrivals.d.ts +31 -0
  257. package/dist/shared/lib/async/arrivals.d.ts.map +1 -0
  258. package/dist/shared/lib/async/arrivals.js +57 -0
  259. package/dist/shared/lib/async/arrivals.js.map +1 -0
  260. package/dist/shared/lib/async/async-queue.d.ts +23 -0
  261. package/dist/shared/lib/async/async-queue.d.ts.map +1 -0
  262. package/dist/shared/lib/async/async-queue.js +80 -0
  263. package/dist/shared/lib/async/async-queue.js.map +1 -0
  264. package/dist/shared/lib/async/deferred.d.ts +12 -0
  265. package/dist/shared/lib/async/deferred.d.ts.map +1 -0
  266. package/dist/shared/lib/async/deferred.js +34 -0
  267. package/dist/shared/lib/async/deferred.js.map +1 -0
  268. package/dist/shared/lib/async/index.d.ts +8 -0
  269. package/dist/shared/lib/async/index.d.ts.map +1 -0
  270. package/dist/shared/lib/async/index.js +5 -0
  271. package/dist/shared/lib/async/index.js.map +1 -0
  272. package/dist/shared/lib/async/run-all.d.ts +8 -0
  273. package/dist/shared/lib/async/run-all.d.ts.map +1 -0
  274. package/dist/shared/lib/async/run-all.js +22 -0
  275. package/dist/shared/lib/async/run-all.js.map +1 -0
  276. package/dist/shared/lib/bytes/bytes.d.ts +18 -0
  277. package/dist/shared/lib/bytes/bytes.d.ts.map +1 -0
  278. package/dist/shared/lib/bytes/bytes.js +48 -0
  279. package/dist/shared/lib/bytes/bytes.js.map +1 -0
  280. package/dist/shared/lib/bytes/index.d.ts +3 -0
  281. package/dist/shared/lib/bytes/index.d.ts.map +1 -0
  282. package/dist/shared/lib/bytes/index.js +2 -0
  283. package/dist/shared/lib/bytes/index.js.map +1 -0
  284. package/dist/shared/lib/clock/clock.d.ts +29 -0
  285. package/dist/shared/lib/clock/clock.d.ts.map +1 -0
  286. package/dist/shared/lib/clock/clock.js +85 -0
  287. package/dist/shared/lib/clock/clock.js.map +1 -0
  288. package/dist/shared/lib/clock/index.d.ts +3 -0
  289. package/dist/shared/lib/clock/index.d.ts.map +1 -0
  290. package/dist/shared/lib/clock/index.js +2 -0
  291. package/dist/shared/lib/clock/index.js.map +1 -0
  292. package/dist/shared/lib/cookies/index.d.ts +3 -0
  293. package/dist/shared/lib/cookies/index.d.ts.map +1 -0
  294. package/dist/shared/lib/cookies/index.js +2 -0
  295. package/dist/shared/lib/cookies/index.js.map +1 -0
  296. package/dist/shared/lib/cookies/set-cookie.d.ts +22 -0
  297. package/dist/shared/lib/cookies/set-cookie.d.ts.map +1 -0
  298. package/dist/shared/lib/cookies/set-cookie.js +89 -0
  299. package/dist/shared/lib/cookies/set-cookie.js.map +1 -0
  300. package/dist/shared/lib/envelope/envelope.d.ts +50 -0
  301. package/dist/shared/lib/envelope/envelope.d.ts.map +1 -0
  302. package/dist/shared/lib/envelope/envelope.js +111 -0
  303. package/dist/shared/lib/envelope/envelope.js.map +1 -0
  304. package/dist/shared/lib/envelope/index.d.ts +3 -0
  305. package/dist/shared/lib/envelope/index.d.ts.map +1 -0
  306. package/dist/shared/lib/envelope/index.js +2 -0
  307. package/dist/shared/lib/envelope/index.js.map +1 -0
  308. package/dist/shared/lib/errors/index.d.ts +3 -0
  309. package/dist/shared/lib/errors/index.d.ts.map +1 -0
  310. package/dist/shared/lib/errors/index.js +2 -0
  311. package/dist/shared/lib/errors/index.js.map +1 -0
  312. package/dist/shared/lib/errors/wirestage-error.d.ts +28 -0
  313. package/dist/shared/lib/errors/wirestage-error.d.ts.map +1 -0
  314. package/dist/shared/lib/errors/wirestage-error.js +16 -0
  315. package/dist/shared/lib/errors/wirestage-error.js.map +1 -0
  316. package/dist/shared/lib/id/id.d.ts +10 -0
  317. package/dist/shared/lib/id/id.d.ts.map +1 -0
  318. package/dist/shared/lib/id/id.js +26 -0
  319. package/dist/shared/lib/id/id.js.map +1 -0
  320. package/dist/shared/lib/id/index.d.ts +2 -0
  321. package/dist/shared/lib/id/index.d.ts.map +1 -0
  322. package/dist/shared/lib/id/index.js +2 -0
  323. package/dist/shared/lib/id/index.js.map +1 -0
  324. package/dist/shared/lib/logger/index.d.ts +3 -0
  325. package/dist/shared/lib/logger/index.d.ts.map +1 -0
  326. package/dist/shared/lib/logger/index.js +2 -0
  327. package/dist/shared/lib/logger/index.js.map +1 -0
  328. package/dist/shared/lib/logger/logger.d.ts +46 -0
  329. package/dist/shared/lib/logger/logger.d.ts.map +1 -0
  330. package/dist/shared/lib/logger/logger.js +67 -0
  331. package/dist/shared/lib/logger/logger.js.map +1 -0
  332. package/dist/shared/lib/match/index.d.ts +3 -0
  333. package/dist/shared/lib/match/index.d.ts.map +1 -0
  334. package/dist/shared/lib/match/index.js +2 -0
  335. package/dist/shared/lib/match/index.js.map +1 -0
  336. package/dist/shared/lib/match/url-matcher.d.ts +27 -0
  337. package/dist/shared/lib/match/url-matcher.d.ts.map +1 -0
  338. package/dist/shared/lib/match/url-matcher.js +88 -0
  339. package/dist/shared/lib/match/url-matcher.js.map +1 -0
  340. package/dist/sse.d.ts +3 -0
  341. package/dist/sse.d.ts.map +1 -0
  342. package/dist/sse.js +3 -0
  343. package/dist/sse.js.map +1 -0
  344. package/dist/webrtc.d.ts +3 -0
  345. package/dist/webrtc.d.ts.map +1 -0
  346. package/dist/webrtc.js +3 -0
  347. package/dist/webrtc.js.map +1 -0
  348. package/dist/websocket.d.ts +3 -0
  349. package/dist/websocket.d.ts.map +1 -0
  350. package/dist/websocket.js +3 -0
  351. package/dist/websocket.js.map +1 -0
  352. package/dist/widgets/stage/index.d.ts +3 -0
  353. package/dist/widgets/stage/index.d.ts.map +1 -0
  354. package/dist/widgets/stage/index.js +2 -0
  355. package/dist/widgets/stage/index.js.map +1 -0
  356. package/dist/widgets/stage/lib/attached-context.d.ts +10 -0
  357. package/dist/widgets/stage/lib/attached-context.d.ts.map +1 -0
  358. package/dist/widgets/stage/lib/attached-context.js +2 -0
  359. package/dist/widgets/stage/lib/attached-context.js.map +1 -0
  360. package/dist/widgets/stage/lib/create-stage.d.ts +12 -0
  361. package/dist/widgets/stage/lib/create-stage.d.ts.map +1 -0
  362. package/dist/widgets/stage/lib/create-stage.js +248 -0
  363. package/dist/widgets/stage/lib/create-stage.js.map +1 -0
  364. package/dist/widgets/stage/lib/http-router.d.ts +35 -0
  365. package/dist/widgets/stage/lib/http-router.d.ts.map +1 -0
  366. package/dist/widgets/stage/lib/http-router.js +455 -0
  367. package/dist/widgets/stage/lib/http-router.js.map +1 -0
  368. package/dist/widgets/stage/lib/page-host.d.ts +36 -0
  369. package/dist/widgets/stage/lib/page-host.d.ts.map +1 -0
  370. package/dist/widgets/stage/lib/page-host.js +240 -0
  371. package/dist/widgets/stage/lib/page-host.js.map +1 -0
  372. package/dist/widgets/stage/lib/page-runtime.d.ts +93 -0
  373. package/dist/widgets/stage/lib/page-runtime.d.ts.map +1 -0
  374. package/dist/widgets/stage/lib/page-runtime.js +247 -0
  375. package/dist/widgets/stage/lib/page-runtime.js.map +1 -0
  376. package/dist/widgets/stage/lib/reads.d.ts +21 -0
  377. package/dist/widgets/stage/lib/reads.d.ts.map +1 -0
  378. package/dist/widgets/stage/lib/reads.js +97 -0
  379. package/dist/widgets/stage/lib/reads.js.map +1 -0
  380. package/dist/widgets/stage/lib/response-stream.d.ts +9 -0
  381. package/dist/widgets/stage/lib/response-stream.d.ts.map +1 -0
  382. package/dist/widgets/stage/lib/response-stream.js +56 -0
  383. package/dist/widgets/stage/lib/response-stream.js.map +1 -0
  384. package/dist/widgets/stage/lib/socket-router.d.ts +25 -0
  385. package/dist/widgets/stage/lib/socket-router.d.ts.map +1 -0
  386. package/dist/widgets/stage/lib/socket-router.js +204 -0
  387. package/dist/widgets/stage/lib/socket-router.js.map +1 -0
  388. package/dist/widgets/stage/model/stage.d.ts +86 -0
  389. package/dist/widgets/stage/model/stage.d.ts.map +1 -0
  390. package/dist/widgets/stage/model/stage.js +2 -0
  391. package/dist/widgets/stage/model/stage.js.map +1 -0
  392. package/package.json +140 -5
  393. package/src/app/playwright/index.ts +7 -0
  394. package/src/app/playwright/lib/fixture.ts +201 -0
  395. package/src/connect.ts +6 -0
  396. package/src/entities/frame/@x/plugin.ts +8 -0
  397. package/src/entities/frame/index.ts +19 -0
  398. package/src/entities/frame/lib/filter.ts +58 -0
  399. package/src/entities/frame/lib/payload.ts +42 -0
  400. package/src/entities/frame/lib/snapshot.ts +105 -0
  401. package/src/entities/frame/lib/timeline.ts +147 -0
  402. package/src/entities/frame/model/frame.ts +191 -0
  403. package/src/entities/plugin/index.ts +36 -0
  404. package/src/entities/plugin/lib/define-plugin.ts +12 -0
  405. package/src/entities/plugin/lib/named.ts +21 -0
  406. package/src/entities/plugin/model/attachment.ts +18 -0
  407. package/src/entities/plugin/model/http.ts +147 -0
  408. package/src/entities/plugin/model/page.ts +110 -0
  409. package/src/entities/plugin/model/plugin.ts +96 -0
  410. package/src/entities/plugin/model/socket.ts +108 -0
  411. package/src/entities/plugin/model/stream.ts +43 -0
  412. package/src/features/connect/index.ts +23 -0
  413. package/src/features/connect/lib/calls.ts +58 -0
  414. package/src/features/connect/lib/client.ts +203 -0
  415. package/src/features/connect/lib/create-connect.ts +164 -0
  416. package/src/features/connect/lib/faults.ts +132 -0
  417. package/src/features/connect/lib/protocol.ts +321 -0
  418. package/src/features/connect/lib/record.ts +48 -0
  419. package/src/features/connect/lib/recorder.ts +306 -0
  420. package/src/features/connect/lib/rules.ts +385 -0
  421. package/src/features/connect/lib/serve.ts +114 -0
  422. package/src/features/connect/lib/status-of.ts +20 -0
  423. package/src/features/connect/lib/stubs.ts +282 -0
  424. package/src/features/connect/lib/universal.ts +100 -0
  425. package/src/features/connect/model/types.ts +305 -0
  426. package/src/features/rest/index.ts +23 -0
  427. package/src/features/rest/lib/calls.ts +31 -0
  428. package/src/features/rest/lib/create-rest.ts +169 -0
  429. package/src/features/rest/lib/path.ts +70 -0
  430. package/src/features/rest/lib/reply.ts +74 -0
  431. package/src/features/rest/model/types.ts +113 -0
  432. package/src/features/sse/index.ts +10 -0
  433. package/src/features/sse/lib/create-sse.ts +128 -0
  434. package/src/features/sse/lib/encode.ts +28 -0
  435. package/src/features/sse/model/types.ts +66 -0
  436. package/src/features/webrtc/index.ts +6 -0
  437. package/src/features/webrtc/lib/create-webrtc.ts +149 -0
  438. package/src/features/webrtc/lib/rtc-page-module.ts +189 -0
  439. package/src/features/webrtc/lib/to-frame.ts +63 -0
  440. package/src/features/webrtc/model/types.ts +80 -0
  441. package/src/features/websocket/index.ts +15 -0
  442. package/src/features/websocket/lib/create-websocket.ts +41 -0
  443. package/src/features/websocket/lib/mock.ts +114 -0
  444. package/src/features/websocket/lib/proxy.ts +141 -0
  445. package/src/features/websocket/lib/wire.ts +78 -0
  446. package/src/features/websocket/model/types.ts +130 -0
  447. package/src/index.ts +111 -0
  448. package/src/playwright.ts +8 -0
  449. package/src/rest.ts +2 -0
  450. package/src/shared/api/http-server/index.ts +2 -0
  451. package/src/shared/api/http-server/listen.ts +71 -0
  452. package/src/shared/api/playwright/index.ts +17 -0
  453. package/src/shared/api/playwright/ports.ts +145 -0
  454. package/src/shared/api/stream-server/index.ts +7 -0
  455. package/src/shared/api/stream-server/stream-server.ts +246 -0
  456. package/src/shared/lib/async/arrivals.ts +91 -0
  457. package/src/shared/lib/async/async-queue.ts +101 -0
  458. package/src/shared/lib/async/deferred.ts +38 -0
  459. package/src/shared/lib/async/index.ts +11 -0
  460. package/src/shared/lib/async/run-all.ts +19 -0
  461. package/src/shared/lib/bytes/bytes.ts +53 -0
  462. package/src/shared/lib/bytes/index.ts +9 -0
  463. package/src/shared/lib/clock/clock.ts +114 -0
  464. package/src/shared/lib/clock/index.ts +2 -0
  465. package/src/shared/lib/cookies/index.ts +2 -0
  466. package/src/shared/lib/cookies/set-cookie.ts +105 -0
  467. package/src/shared/lib/envelope/envelope.ts +133 -0
  468. package/src/shared/lib/envelope/index.ts +9 -0
  469. package/src/shared/lib/errors/index.ts +5 -0
  470. package/src/shared/lib/errors/wirestage-error.ts +50 -0
  471. package/src/shared/lib/id/id.ts +29 -0
  472. package/src/shared/lib/id/index.ts +1 -0
  473. package/src/shared/lib/logger/index.ts +12 -0
  474. package/src/shared/lib/logger/logger.ts +126 -0
  475. package/src/shared/lib/match/index.ts +6 -0
  476. package/src/shared/lib/match/url-matcher.ts +107 -0
  477. package/src/sse.ts +2 -0
  478. package/src/webrtc.ts +2 -0
  479. package/src/websocket.ts +2 -0
  480. package/src/widgets/stage/index.ts +9 -0
  481. package/src/widgets/stage/lib/attached-context.ts +10 -0
  482. package/src/widgets/stage/lib/create-stage.ts +305 -0
  483. package/src/widgets/stage/lib/http-router.ts +620 -0
  484. package/src/widgets/stage/lib/page-host.ts +375 -0
  485. package/src/widgets/stage/lib/page-runtime.ts +314 -0
  486. package/src/widgets/stage/lib/reads.ts +128 -0
  487. package/src/widgets/stage/lib/response-stream.ts +66 -0
  488. package/src/widgets/stage/lib/socket-router.ts +271 -0
  489. package/src/widgets/stage/model/stage.ts +108 -0
@@ -0,0 +1,114 @@
1
+ import { createServer as createHttpServer } from "node:http";
2
+ import { createServer as createHttp2Server } from "node:http2";
3
+ import type { Server } from "node:net";
4
+
5
+ import type { DescMethod, DescService } from "@bufbuild/protobuf";
6
+ import {
7
+ type ConnectRouter,
8
+ createContextValues,
9
+ type ServiceImpl,
10
+ } from "@connectrpc/connect";
11
+ import { connectNodeAdapter } from "@connectrpc/connect-node";
12
+
13
+ import { listen } from "../../../shared/api/http-server/index.js";
14
+ import type { RpcServer, ServeOptions } from "../model/types.js";
15
+ import { detectFormat } from "./protocol.js";
16
+ import { kCall, type Recorder, recordingImpl } from "./recorder.js";
17
+
18
+ export interface ServeDeps {
19
+ readonly recorder: Recorder;
20
+ readonly correlation: () => string;
21
+ }
22
+
23
+ /**
24
+ * Route registrations, with every implementation wrapped for recording.
25
+ * The caller writes ordinary Connect routes; nothing about recording leaks
26
+ * into its code.
27
+ */
28
+ function recordingRouter(
29
+ router: ConnectRouter,
30
+ deps: ServeDeps,
31
+ ): ConnectRouter {
32
+ // Bound to the object it came from: a class instance or a stateful fake
33
+ // reads its own fields, and Connect would have called it that way.
34
+ const wrap = (method: DescMethod, impl: unknown, owner?: unknown) =>
35
+ recordingImpl(
36
+ method,
37
+ (impl as (...args: never[]) => unknown).bind(owner) as never,
38
+ deps.recorder,
39
+ );
40
+ const proxy: ConnectRouter = {
41
+ get handlers() {
42
+ return router.handlers;
43
+ },
44
+ service(service, implementation, options) {
45
+ const wrapped: Record<string, unknown> = {};
46
+ for (const method of (service as DescService).methods) {
47
+ const impl = (implementation as Record<string, unknown>)[
48
+ method.localName
49
+ ];
50
+ if (impl !== undefined)
51
+ wrapped[method.localName] = wrap(method, impl, implementation);
52
+ }
53
+ router.service(
54
+ service,
55
+ wrapped as Partial<ServiceImpl<typeof service>>,
56
+ options,
57
+ );
58
+ return proxy;
59
+ },
60
+ rpc(method, impl, options) {
61
+ router.rpc(method, wrap(method, impl) as typeof impl, options);
62
+ return proxy;
63
+ },
64
+ };
65
+ return proxy;
66
+ }
67
+
68
+ /** Serve Connect routes on a port of their own, recording every call. */
69
+ export async function serveRoutes(
70
+ routes: (router: ConnectRouter) => void,
71
+ options: ServeOptions,
72
+ deps: ServeDeps,
73
+ ): Promise<RpcServer> {
74
+ const protocols = new Set(
75
+ options.protocols ?? ["connect", "grpc-web", "grpc"],
76
+ );
77
+ const handler = connectNodeAdapter({
78
+ connect: protocols.has("connect"),
79
+ grpcWeb: protocols.has("grpc-web"),
80
+ grpc: protocols.has("grpc"),
81
+ routes: (router) => routes(recordingRouter(router, deps)),
82
+ contextValues: (request) =>
83
+ createContextValues().set(kCall, {
84
+ correlation: deps.correlation(),
85
+ // A client outside the browser, answered by the served fake.
86
+ from: "network",
87
+ answeredBy: "server",
88
+ // Node always sets method and url on a server request; the types do
89
+ // not say so. A Connect GET carries no content type at all.
90
+ rpcProtocol: detectFormat({
91
+ method: String(request.method),
92
+ url: new URL(String(request.url), "http://localhost"),
93
+ headers: {
94
+ "content-type": String(request.headers["content-type"] ?? ""),
95
+ },
96
+ })?.protocol,
97
+ }),
98
+ });
99
+ const http2 = options.http2 ?? protocols.has("grpc");
100
+ const server: Server = http2
101
+ ? createHttp2Server(handler)
102
+ : createHttpServer(handler);
103
+ const listening = await listen(server, {
104
+ name: "wirestage rpc server",
105
+ protocol: "http",
106
+ host: options.host,
107
+ port: options.port,
108
+ });
109
+ return {
110
+ url: listening.url,
111
+ port: listening.port,
112
+ close: () => listening.close(),
113
+ };
114
+ }
@@ -0,0 +1,20 @@
1
+ import { ConnectError } from "@connectrpc/connect";
2
+
3
+ /**
4
+ * The gRPC status a call ended with: 0 when it resolved, the server's code
5
+ * when it failed. For asserting a refusal without a try/catch:
6
+ *
7
+ * expect(await statusOf(orders.cancel(ref))).toBe(Code.PermissionDenied);
8
+ *
9
+ * Anything that is not a `ConnectError` -- a bug in the test, say -- is
10
+ * rethrown rather than read as a status.
11
+ */
12
+ export async function statusOf(call: Promise<unknown>): Promise<number> {
13
+ try {
14
+ await call;
15
+ return 0;
16
+ } catch (error) {
17
+ if (error instanceof ConnectError) return error.code;
18
+ throw error;
19
+ }
20
+ }
@@ -0,0 +1,282 @@
1
+ import type {
2
+ DescMessage,
3
+ DescMethod,
4
+ DescMethodServerStreaming,
5
+ DescMethodUnary,
6
+ DescService,
7
+ MessageInitShape,
8
+ MessageShape,
9
+ } from "@bufbuild/protobuf";
10
+ import {
11
+ type Code,
12
+ Code as Codes,
13
+ ConnectError,
14
+ type HandlerContext,
15
+ type ServiceImpl,
16
+ } from "@connectrpc/connect";
17
+
18
+ import type {
19
+ HttpRuleHandle,
20
+ PluginContext,
21
+ } from "../../../entities/plugin/index.js";
22
+ import {
23
+ type Arrivals,
24
+ createArrivals,
25
+ createAsyncQueue,
26
+ createDeferred,
27
+ } from "../../../shared/lib/async/index.js";
28
+ import { WirestageError } from "../../../shared/lib/errors/index.js";
29
+ import type {
30
+ StreamCall,
31
+ StreamEnd,
32
+ StreamStub,
33
+ StubHandle,
34
+ StubOptions,
35
+ UnaryReply,
36
+ UnaryStub,
37
+ } from "../model/types.js";
38
+ import { endpointOf, kCall, type Recorder } from "./recorder.js";
39
+ import type { AnyImpl, RpcRules } from "./rules.js";
40
+
41
+ export const handleOf = (rule: HttpRuleHandle): StubHandle => ({
42
+ get hits() {
43
+ return rule.hits;
44
+ },
45
+ remove: () => rule.remove(),
46
+ });
47
+
48
+ /** The status a stub fails a call with. */
49
+ export const failure = (
50
+ code: Code,
51
+ message: string | undefined,
52
+ ): ConnectError => new ConnectError(message ?? `stubbed ${Codes[code]}`, code);
53
+
54
+ /** An implementation that fails every call, for either kind a page can call. */
55
+ export const failingImpl = (
56
+ method: DescMethod,
57
+ code: Code,
58
+ message: string | undefined,
59
+ ): AnyImpl =>
60
+ (method.methodKind === "server_streaming"
61
+ ? async function* () {
62
+ yield* [];
63
+ throw failure(code, message);
64
+ }
65
+ : async () => {
66
+ throw failure(code, message);
67
+ }) as AnyImpl;
68
+
69
+ /** One method answered by one implementation. */
70
+ const stubMethod = <I extends DescMessage>(
71
+ rules: RpcRules,
72
+ method: DescMethod,
73
+ impl: AnyImpl,
74
+ options: StubOptions<I>,
75
+ label: string,
76
+ ): Promise<HttpRuleHandle> => {
77
+ const handler = rules.handler(method, impl);
78
+ return rules.add({
79
+ method,
80
+ label,
81
+ options,
82
+ respond: (view) => rules.answer(handler, method, view),
83
+ });
84
+ };
85
+
86
+ export async function stubService<S extends DescService>(
87
+ rules: RpcRules,
88
+ service: S,
89
+ impl: Partial<ServiceImpl<S>>,
90
+ options: StubOptions,
91
+ ): Promise<StubHandle> {
92
+ const added: HttpRuleHandle[] = [];
93
+ const remove = async () => {
94
+ await Promise.all(added.map((rule) => rule.remove()));
95
+ };
96
+ try {
97
+ for (const method of service.methods) {
98
+ const own = (impl as Record<string, AnyImpl | undefined>)[
99
+ method.localName
100
+ ];
101
+ if (own !== undefined)
102
+ added.push(
103
+ await stubMethod(
104
+ rules,
105
+ method,
106
+ // A class instance or a stateful object: its methods need it.
107
+ own.bind(impl) as AnyImpl,
108
+ options,
109
+ `stub ${endpointOf(method)}`,
110
+ ),
111
+ );
112
+ }
113
+ } catch (error) {
114
+ // All of the service or none of it.
115
+ await remove();
116
+ throw error;
117
+ }
118
+ if (added.length === 0)
119
+ throw new WirestageError(
120
+ "INVALID_ARGUMENT",
121
+ `stub for ${service.typeName} implements none of its methods`,
122
+ );
123
+ return {
124
+ get hits() {
125
+ return added.reduce((sum, rule) => sum + rule.hits, 0);
126
+ },
127
+ remove,
128
+ };
129
+ }
130
+
131
+ export async function stubUnary<I extends DescMessage, O extends DescMessage>(
132
+ context: PluginContext,
133
+ rules: RpcRules,
134
+ method: DescMethodUnary<I, O>,
135
+ reply: UnaryReply<I, O>,
136
+ options: StubOptions<I>,
137
+ ): Promise<UnaryStub<I>> {
138
+ const requests = createArrivals<MessageShape<I>>({
139
+ clock: context.clock,
140
+ label: `${endpointOf(method)} request`,
141
+ });
142
+ const impl = async (request: MessageShape<I>, handler: HandlerContext) => {
143
+ requests.push(request);
144
+ return typeof reply === "function" ? reply(request, handler) : reply;
145
+ };
146
+ const rule = await stubMethod(
147
+ rules,
148
+ method,
149
+ impl as AnyImpl,
150
+ options,
151
+ `unary ${endpointOf(method)}`,
152
+ );
153
+ return {
154
+ ...handleOf(rule),
155
+ get hits() {
156
+ return rule.hits;
157
+ },
158
+ get requests() {
159
+ return requests.items;
160
+ },
161
+ next: (waitOptions) => requests.next(waitOptions),
162
+ };
163
+ }
164
+
165
+ export async function stubStream<I extends DescMessage, O extends DescMessage>(
166
+ context: PluginContext,
167
+ rules: RpcRules,
168
+ recorder: Recorder,
169
+ method: DescMethodServerStreaming<I, O>,
170
+ options: StubOptions<I>,
171
+ live: boolean,
172
+ ): Promise<StreamStub<I, O>> {
173
+ if (!live)
174
+ throw new WirestageError(
175
+ "UNSUPPORTED",
176
+ "stream() needs live streaming; it was configured as `buffered`",
177
+ );
178
+ /** Calls the stub took: each should become a stream. */
179
+ let taken = 0;
180
+ const calls: Arrivals<StreamCall<I, O>> = createArrivals({
181
+ clock: context.clock,
182
+ label: `${endpointOf(method)} stream`,
183
+ // The stub took the call, yet no stream came of it: the redirect to
184
+ // the stream server is what went missing.
185
+ hint: (): string | undefined =>
186
+ taken > calls.items.length
187
+ ? `${taken - calls.items.length} call(s) matched but never reached the local stream server — see "Live streams" in docs/troubleshooting.md`
188
+ : undefined,
189
+ });
190
+ const impl = async function* (
191
+ request: MessageShape<I>,
192
+ handler: HandlerContext,
193
+ ) {
194
+ const info = handler.values.get(kCall);
195
+ const queue = createAsyncQueue<MessageInitShape<O>>();
196
+ const closed = createDeferred<StreamEnd>();
197
+ /** Once the response itself is over, not merely decided. */
198
+ const over = async () => {
199
+ await info.over;
200
+ };
201
+ const call: StreamCall<I, O> = {
202
+ request,
203
+ requestHeaders: handler.requestHeader,
204
+ protocol: info.rpcProtocol,
205
+ send: (message) => queue.push(message),
206
+ async end() {
207
+ queue.close();
208
+ await over();
209
+ },
210
+ async fail(code, message) {
211
+ queue.fail(failure(code, message));
212
+ await over();
213
+ },
214
+ async cut() {
215
+ // Settled and recorded here, not by what follows: the connection
216
+ // resets asynchronously, after the queue has already ended, and
217
+ // the implementation returning then must not read as an OK.
218
+ closed.resolve("cut");
219
+ recorder.fault(info, method, "cut");
220
+ info.cut?.();
221
+ queue.close();
222
+ await over();
223
+ },
224
+ closed: closed.promise,
225
+ };
226
+ handler.signal.addEventListener("abort", () => {
227
+ if (closed.settled) return;
228
+ closed.resolve("cancelled");
229
+ recorder.fault(info, method, "cancelled", { by: "page" });
230
+ queue.close();
231
+ });
232
+ calls.push(call);
233
+ try {
234
+ for await (const message of queue) yield message;
235
+ closed.resolve("ended");
236
+ } catch (error) {
237
+ closed.resolve("failed");
238
+ throw error;
239
+ }
240
+ };
241
+ const handler = rules.handler(method, impl as AnyImpl);
242
+ const rule = await rules.add({
243
+ method,
244
+ label: `stream ${endpointOf(method)}`,
245
+ options,
246
+ respond(view) {
247
+ taken += 1;
248
+ return rules.answer(handler, method, view);
249
+ },
250
+ });
251
+ return {
252
+ ...handleOf(rule),
253
+ get hits() {
254
+ return rule.hits;
255
+ },
256
+ next: (waitOptions) => calls.next(waitOptions),
257
+ get calls() {
258
+ return calls.items;
259
+ },
260
+ async broadcast(message) {
261
+ for (const call of calls.items) await call.send(message).catch(() => {});
262
+ },
263
+ };
264
+ }
265
+
266
+ export async function stubFailure<I extends DescMessage>(
267
+ rules: RpcRules,
268
+ method: DescMethod & { readonly input: I },
269
+ code: Code,
270
+ message: string | undefined,
271
+ options: StubOptions<I>,
272
+ ): Promise<StubHandle> {
273
+ return handleOf(
274
+ await stubMethod(
275
+ rules,
276
+ method,
277
+ failingImpl(method, code, message),
278
+ options,
279
+ `fail ${endpointOf(method)}`,
280
+ ),
281
+ );
282
+ }
@@ -0,0 +1,100 @@
1
+ import type { ContextValues } from "@connectrpc/connect";
2
+ import type {
3
+ UniversalServerRequest,
4
+ UniversalServerResponse,
5
+ } from "@connectrpc/connect/protocol";
6
+
7
+ import type {
8
+ HttpRequestView,
9
+ ResponseStream,
10
+ } from "../../../entities/plugin/index.js";
11
+ import { concatBytes } from "../../../shared/lib/bytes/index.js";
12
+ import { WirestageError } from "../../../shared/lib/errors/index.js";
13
+
14
+ /** A Playwright request, as the request Connect's handlers expect. */
15
+ export function toUniversalRequest(
16
+ view: HttpRequestView,
17
+ contextValues: ContextValues,
18
+ signal: AbortSignal = new AbortController().signal,
19
+ ): UniversalServerRequest {
20
+ const body = view.body();
21
+ return {
22
+ httpVersion: "1.1",
23
+ url: view.url.href,
24
+ method: view.method,
25
+ header: new Headers(view.headers),
26
+ body: (async function* () {
27
+ if (body.byteLength > 0) yield body;
28
+ })(),
29
+ signal,
30
+ contextValues,
31
+ };
32
+ }
33
+
34
+ /**
35
+ * A response's headers as a plain record. `set-cookie` keeps every value,
36
+ * one per line, which is how a route and a Node response take several.
37
+ */
38
+ function headersOf(response: UniversalServerResponse): Record<string, string> {
39
+ const headers: Record<string, string> = {};
40
+ response.header?.forEach((value, name) => {
41
+ headers[name] = value;
42
+ });
43
+ const cookies = response.header?.getSetCookie() ?? [];
44
+ if (cookies.length > 1) headers["set-cookie"] = cookies.join("\n");
45
+ return headers;
46
+ }
47
+
48
+ /**
49
+ * Connect and gRPC-web carry their trailers in the headers or the body; only
50
+ * native gRPC needs HTTP trailers, which neither a route nor the stream
51
+ * server sends — and which a browser could not have asked for anyway.
52
+ */
53
+ function refuseTrailers(response: UniversalServerResponse): void {
54
+ let trailers = 0;
55
+ response.trailer?.forEach(() => {
56
+ trailers += 1;
57
+ });
58
+ if (trailers > 0)
59
+ throw new WirestageError(
60
+ "UNSUPPORTED",
61
+ "this response needs HTTP trailers (native gRPC), which a browser route cannot send; use serve() for gRPC clients",
62
+ );
63
+ }
64
+
65
+ export interface CollectedResponse {
66
+ readonly status: number;
67
+ readonly headers: Readonly<Record<string, string>>;
68
+ readonly body: Uint8Array;
69
+ }
70
+
71
+ /** Read a handler's whole response, for `route.fulfill`. */
72
+ export async function collectResponse(
73
+ response: UniversalServerResponse,
74
+ ): Promise<CollectedResponse> {
75
+ const chunks: Uint8Array[] = [];
76
+ for await (const chunk of response.body ?? []) chunks.push(chunk);
77
+ refuseTrailers(response);
78
+ return {
79
+ status: response.status,
80
+ headers: headersOf(response),
81
+ body: concatBytes(chunks),
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Write a handler's response to an open stream as the handler produces it:
87
+ * the head with the first chunk, as a real Connect server sends it, and each
88
+ * message as soon as the implementation yields it.
89
+ */
90
+ export async function pipeResponse(
91
+ response: UniversalServerResponse,
92
+ stream: ResponseStream,
93
+ ): Promise<void> {
94
+ stream.head(response.status, headersOf(response));
95
+ // A streaming handler always answers with a body, error trailers included.
96
+ for await (const chunk of response.body as AsyncIterable<Uint8Array>)
97
+ await stream.write(chunk);
98
+ refuseTrailers(response);
99
+ await stream.end();
100
+ }