@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,91 @@
1
+ import type { Clock } from "../clock/index.js";
2
+ import { WirestageError } from "../errors/index.js";
3
+
4
+ export interface ArrivalWaitOptions {
5
+ /** Milliseconds to wait. Defaults to the value given at creation. */
6
+ readonly timeout?: number;
7
+ }
8
+
9
+ export interface Arrivals<T> {
10
+ push(item: T): void;
11
+ /**
12
+ * The next item `next` has not returned yet, waiting for one if needed.
13
+ * Items that arrived before the call count: a test that asks for the stream
14
+ * the page opened during `goto` must not miss it by asking too late.
15
+ */
16
+ next(options?: ArrivalWaitOptions): Promise<T>;
17
+ readonly items: readonly T[];
18
+ readonly latest: T | undefined;
19
+ }
20
+
21
+ export interface ArrivalsOptions {
22
+ readonly clock: Clock;
23
+ /** Names the thing being waited for in the TIMEOUT message. */
24
+ readonly label: string;
25
+ readonly timeout?: number;
26
+ /**
27
+ * What the waiter knows about why nothing arrived, added to the TIMEOUT
28
+ * message: "the page never asked" and "it asked, and the answer got
29
+ * lost" call for different fixes.
30
+ */
31
+ readonly hint?: () => string | undefined;
32
+ }
33
+
34
+ /** Things that show up over time — connections, calls, messages — and a way to await the next. */
35
+ export function createArrivals<T>(options: ArrivalsOptions): Arrivals<T> {
36
+ const items: T[] = [];
37
+ let cursor = 0;
38
+ const waiters = new Set<() => void>();
39
+ const defaultTimeout = options.timeout ?? 5_000;
40
+
41
+ /** Resolves true on the next push, false when `ms` pass first. */
42
+ const pushedWithin = async (ms: number): Promise<boolean> => {
43
+ const abort = new AbortController();
44
+ let resolvePushed!: (pushed: boolean) => void;
45
+ const pushed = new Promise<boolean>((resolve) => {
46
+ resolvePushed = resolve;
47
+ });
48
+ const wake = () => resolvePushed(true);
49
+ waiters.add(wake);
50
+ const expired = options.clock
51
+ .sleep(ms, abort.signal)
52
+ .then(() => false)
53
+ .catch(() => true);
54
+ const result = await Promise.race([pushed, expired]);
55
+ waiters.delete(wake);
56
+ abort.abort();
57
+ return result;
58
+ };
59
+
60
+ return {
61
+ push(item) {
62
+ items.push(item);
63
+ for (const wake of [...waiters]) wake();
64
+ },
65
+ async next(waitOptions = {}) {
66
+ const timeout = waitOptions.timeout ?? defaultTimeout;
67
+ const deadline = options.clock.now() + timeout;
68
+ // A loop, not a single wait: two callers woken by one push race for
69
+ // one item, and the loser has to go back to waiting.
70
+ for (;;) {
71
+ if (cursor < items.length) return items[cursor++] as T;
72
+ const remaining = deadline - options.clock.now();
73
+ if (remaining <= 0 || !(await pushedWithin(remaining))) {
74
+ if (cursor < items.length) return items[cursor++] as T;
75
+ const hint = options.hint?.();
76
+ throw new WirestageError(
77
+ "TIMEOUT",
78
+ `no ${options.label} arrived within ${timeout} ms (${items.length} seen so far)${hint === undefined ? "" : `; ${hint}`}`,
79
+ { details: { label: options.label, timeout, seen: items.length } },
80
+ );
81
+ }
82
+ }
83
+ },
84
+ get items() {
85
+ return items;
86
+ },
87
+ get latest() {
88
+ return items.at(-1);
89
+ },
90
+ };
91
+ }
@@ -0,0 +1,101 @@
1
+ import { WirestageError } from "../errors/index.js";
2
+ import { createDeferred, type Deferred } from "./deferred.js";
3
+
4
+ export interface AsyncQueue<T> extends AsyncIterable<T> {
5
+ /**
6
+ * Queue a value. Resolves once the consumer has taken it and come back
7
+ * for the next — for a stream being written, once the value is on the
8
+ * wire. Rejects with `CLOSED` when the queue was closed first, or when
9
+ * the consumer went away before getting through the value.
10
+ */
11
+ push(value: T): Promise<void>;
12
+ /** End iteration once the queued values are consumed. */
13
+ close(): void;
14
+ /** End iteration with `reason` once the queued values are consumed. */
15
+ fail(reason: unknown): void;
16
+ readonly closed: boolean;
17
+ /** Values pushed but not consumed yet. */
18
+ readonly size: number;
19
+ }
20
+
21
+ interface Entry<T> {
22
+ readonly value: T;
23
+ readonly done: Deferred<void>;
24
+ }
25
+
26
+ /**
27
+ * A single-consumer queue that a test pushes into and a stream implementation
28
+ * iterates. Values pushed before the consumer starts are kept, so a test may
29
+ * queue the first messages before the page has even opened the stream.
30
+ */
31
+ export function createAsyncQueue<T>(): AsyncQueue<T> {
32
+ const entries: Entry<T>[] = [];
33
+ let waiter: (() => void) | undefined;
34
+ let closed = false;
35
+ let failure: { readonly reason: unknown } | undefined;
36
+ const wake = () => {
37
+ const w = waiter;
38
+ waiter = undefined;
39
+ w?.();
40
+ };
41
+ const lost = () =>
42
+ new WirestageError(
43
+ "CLOSED",
44
+ "the queue closed before the value got through",
45
+ );
46
+ return {
47
+ push(value) {
48
+ const done = createDeferred<void>();
49
+ if (closed) done.reject(lost());
50
+ else {
51
+ entries.push({ value, done });
52
+ wake();
53
+ }
54
+ return done.promise;
55
+ },
56
+ close() {
57
+ closed = true;
58
+ wake();
59
+ },
60
+ fail(reason) {
61
+ if (!closed) failure = { reason };
62
+ closed = true;
63
+ wake();
64
+ },
65
+ get closed() {
66
+ return closed;
67
+ },
68
+ get size() {
69
+ return entries.length;
70
+ },
71
+ async *[Symbol.asyncIterator]() {
72
+ /** The value handed out last: through once the consumer is back. */
73
+ let out: Deferred<void> | undefined;
74
+ try {
75
+ for (;;) {
76
+ out?.resolve();
77
+ out = undefined;
78
+ const entry = entries.shift();
79
+ if (entry !== undefined) {
80
+ out = entry.done;
81
+ yield entry.value;
82
+ continue;
83
+ }
84
+ if (closed) {
85
+ if (failure) throw failure.reason;
86
+ return;
87
+ }
88
+ await new Promise<void>((resolve) => {
89
+ waiter = resolve;
90
+ });
91
+ }
92
+ } finally {
93
+ // The consumer stopped early: what it held, and what it never
94
+ // reached, did not get through.
95
+ closed = true;
96
+ out?.reject(lost());
97
+ for (const entry of entries.splice(0)) entry.done.reject(lost());
98
+ }
99
+ },
100
+ };
101
+ }
@@ -0,0 +1,38 @@
1
+ export interface Deferred<T> {
2
+ readonly promise: Promise<T>;
3
+ resolve(value: T): void;
4
+ reject(reason: unknown): void;
5
+ readonly settled: boolean;
6
+ }
7
+
8
+ /**
9
+ * A promise with its resolvers. Settling twice is a no-op, so racing paths
10
+ * (a client disconnect and an explicit end) can both try without a guard.
11
+ */
12
+ export function createDeferred<T>(): Deferred<T> {
13
+ let settled = false;
14
+ let resolveFn!: (value: T) => void;
15
+ let rejectFn!: (reason: unknown) => void;
16
+ const promise = new Promise<T>((resolve, reject) => {
17
+ resolveFn = resolve;
18
+ rejectFn = reject;
19
+ });
20
+ // A deferred nobody awaits must not surface as an unhandled rejection.
21
+ promise.catch(() => {});
22
+ return {
23
+ promise,
24
+ resolve(value) {
25
+ if (settled) return;
26
+ settled = true;
27
+ resolveFn(value);
28
+ },
29
+ reject(reason) {
30
+ if (settled) return;
31
+ settled = true;
32
+ rejectFn(reason);
33
+ },
34
+ get settled() {
35
+ return settled;
36
+ },
37
+ };
38
+ }
@@ -0,0 +1,11 @@
1
+ export type {
2
+ Arrivals,
3
+ ArrivalsOptions,
4
+ ArrivalWaitOptions,
5
+ } from "./arrivals.js";
6
+ export { createArrivals } from "./arrivals.js";
7
+ export type { AsyncQueue } from "./async-queue.js";
8
+ export { createAsyncQueue } from "./async-queue.js";
9
+ export type { Deferred } from "./deferred.js";
10
+ export { createDeferred } from "./deferred.js";
11
+ export { runAll } from "./run-all.js";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Run every step in order even when one fails, then throw what failed: the
3
+ * one error, or an `AggregateError` of several. For teardown, where stopping
4
+ * at the first failure leaves everything after it — a server, a route —
5
+ * behind.
6
+ */
7
+ export async function runAll(steps: readonly (() => unknown)[]): Promise<void> {
8
+ const failures: unknown[] = [];
9
+ for (const step of steps) {
10
+ try {
11
+ await step();
12
+ } catch (error) {
13
+ failures.push(error);
14
+ }
15
+ }
16
+ if (failures.length === 1) throw failures[0];
17
+ if (failures.length > 1)
18
+ throw new AggregateError(failures, "several teardown steps failed");
19
+ }
@@ -0,0 +1,53 @@
1
+ const encoder = new TextEncoder();
2
+ const decoder = new TextDecoder();
3
+
4
+ /** Anything the wire can carry: binary views or text (encoded as UTF-8). */
5
+ export type BytesLike = Uint8Array | ArrayBuffer | ArrayBufferView | string;
6
+
7
+ /**
8
+ * View `value` as bytes without copying when it already is binary.
9
+ *
10
+ * A `Buffer` is a `Uint8Array`, so Playwright's buffers pass straight through;
11
+ * copying every recorded payload would double the memory a long test holds.
12
+ */
13
+ export function toBytes(value: BytesLike): Uint8Array {
14
+ if (typeof value === "string") return encoder.encode(value);
15
+ if (value instanceof Uint8Array) return value;
16
+ if (value instanceof ArrayBuffer) return new Uint8Array(value);
17
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
18
+ }
19
+
20
+ /** Decode UTF-8. Invalid sequences become U+FFFD instead of throwing. */
21
+ export function utf8(bytes: Uint8Array): string {
22
+ return decoder.decode(bytes);
23
+ }
24
+
25
+ /** Join chunks into one array. One chunk is returned as is. */
26
+ export function concatBytes(chunks: readonly Uint8Array[]): Uint8Array {
27
+ if (chunks.length === 1) return chunks[0] as Uint8Array;
28
+ let length = 0;
29
+ for (const chunk of chunks) length += chunk.byteLength;
30
+ const out = new Uint8Array(length);
31
+ let offset = 0;
32
+ for (const chunk of chunks) {
33
+ out.set(chunk, offset);
34
+ offset += chunk.byteLength;
35
+ }
36
+ return out;
37
+ }
38
+
39
+ export function toBase64(bytes: Uint8Array): string {
40
+ return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString(
41
+ "base64",
42
+ );
43
+ }
44
+
45
+ export function fromBase64(text: string): Uint8Array {
46
+ const buffer = Buffer.from(text, "base64");
47
+ return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
48
+ }
49
+
50
+ /** A Node Buffer over the same memory, for APIs that insist on Buffer. */
51
+ export function toBuffer(bytes: Uint8Array): Buffer {
52
+ return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
53
+ }
@@ -0,0 +1,9 @@
1
+ export type { BytesLike } from "./bytes.js";
2
+ export {
3
+ concatBytes,
4
+ fromBase64,
5
+ toBase64,
6
+ toBuffer,
7
+ toBytes,
8
+ utf8,
9
+ } from "./bytes.js";
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Time, as a port. Waits, timeouts and frame timestamps all go through it, so a
3
+ * unit test can drive a 5-second timeout in microseconds with a manual clock
4
+ * instead of sleeping.
5
+ */
6
+ export interface Clock {
7
+ /** Milliseconds since the Unix epoch, with sub-millisecond precision. */
8
+ now(): number;
9
+ /** Resolve after `ms`, or reject with the signal's reason if it aborts first. */
10
+ sleep(ms: number, signal?: AbortSignal): Promise<void>;
11
+ }
12
+
13
+ /** The longest delay a Node timer takes: 2^31 - 1 ms, about 24.8 days. */
14
+ const MAX_TIMER_MS = 2_147_483_647;
15
+
16
+ /**
17
+ * Wall-clock time built from `performance`, not `Date.now()`: it has
18
+ * sub-millisecond resolution, and a page's `performance.timeOrigin + now()` is on
19
+ * the same scale, so page frames and Node frames sort together.
20
+ */
21
+ export function createSystemClock(): Clock {
22
+ return {
23
+ now: () => performance.timeOrigin + performance.now(),
24
+ sleep: (ms, signal) =>
25
+ new Promise<void>((resolve, reject) => {
26
+ if (signal?.aborted) {
27
+ reject(signal.reason);
28
+ return;
29
+ }
30
+ const onAbort = () => {
31
+ clearTimeout(timer);
32
+ reject(signal?.reason);
33
+ };
34
+ const timer = setTimeout(
35
+ () => {
36
+ signal?.removeEventListener("abort", onAbort);
37
+ resolve();
38
+ },
39
+ // A longer delay overflows the timer to 1 ms: "wait forever"
40
+ // (`timeout: Infinity`) would time out at once.
41
+ Math.min(ms, MAX_TIMER_MS),
42
+ );
43
+ signal?.addEventListener("abort", onAbort, { once: true });
44
+ }),
45
+ };
46
+ }
47
+
48
+ export interface ManualClock extends Clock {
49
+ /**
50
+ * Move time forward, resolving every sleep that falls due, earliest first.
51
+ * Awaiting it lets the continuations of those sleeps run before it returns.
52
+ */
53
+ advance(ms: number): Promise<void>;
54
+ /** Sleeps that have not fallen due yet. */
55
+ readonly pending: number;
56
+ }
57
+
58
+ interface Timer {
59
+ readonly due: number;
60
+ readonly resolve: () => void;
61
+ }
62
+
63
+ /** A clock that only moves when told to. For tests of timing behavior. */
64
+ export function createManualClock(start = 0): ManualClock {
65
+ let time = start;
66
+ let timers: Timer[] = [];
67
+ const settle = async () => {
68
+ // Several turns: a resolved sleep's continuation may itself await
69
+ // another promise before reaching the code under test.
70
+ for (let i = 0; i < 10; i++) await Promise.resolve();
71
+ };
72
+ return {
73
+ now: () => time,
74
+ sleep(ms, signal) {
75
+ return new Promise<void>((resolve, reject) => {
76
+ if (signal?.aborted) {
77
+ reject(signal.reason);
78
+ return;
79
+ }
80
+ const timer: Timer = {
81
+ due: time + ms,
82
+ resolve: () => {
83
+ signal?.removeEventListener("abort", onAbort);
84
+ resolve();
85
+ },
86
+ };
87
+ const onAbort = () => {
88
+ timers = timers.filter((t) => t !== timer);
89
+ reject(signal?.reason);
90
+ };
91
+ signal?.addEventListener("abort", onAbort, { once: true });
92
+ timers.push(timer);
93
+ });
94
+ },
95
+ async advance(ms) {
96
+ const target = time + ms;
97
+ for (;;) {
98
+ const next = timers
99
+ .filter((t) => t.due <= target)
100
+ .sort((a, b) => a.due - b.due)[0];
101
+ if (next === undefined) break;
102
+ timers = timers.filter((t) => t !== next);
103
+ time = next.due;
104
+ next.resolve();
105
+ await settle();
106
+ }
107
+ time = target;
108
+ await settle();
109
+ },
110
+ get pending() {
111
+ return timers.length;
112
+ },
113
+ };
114
+ }
@@ -0,0 +1,2 @@
1
+ export type { Clock, ManualClock } from "./clock.js";
2
+ export { createManualClock, createSystemClock } from "./clock.js";
@@ -0,0 +1,2 @@
1
+ export type { CookieInit } from "./set-cookie.js";
2
+ export { parseSetCookie } from "./set-cookie.js";
@@ -0,0 +1,105 @@
1
+ /** A cookie the way a browser context stores one: Playwright's `addCookies` shape. */
2
+ export interface CookieInit {
3
+ readonly name: string;
4
+ readonly value: string;
5
+ /** A leading dot covers subdomains, as Playwright spells it; none is host-only. */
6
+ readonly domain: string;
7
+ readonly path: string;
8
+ /** Seconds since the epoch; absent for a session cookie. */
9
+ readonly expires?: number;
10
+ readonly httpOnly: boolean;
11
+ readonly secure: boolean;
12
+ readonly sameSite?: "Strict" | "Lax" | "None";
13
+ }
14
+
15
+ /** The latest expiry a browser context accepts: 9999-12-31, in seconds. */
16
+ const MAX_EXPIRES = 253_402_300_799;
17
+
18
+ /**
19
+ * One `Set-Cookie` line, stored the way a browser would store it for a response
20
+ * from `url` (RFC 6265 §5.2-5.3): `Domain` covers subdomains and no `Domain`
21
+ * is host-only, no `Path` is the request path's directory, and `Max-Age` beats
22
+ * `Expires`. Undefined for a line a browser would ignore: one with no cookie
23
+ * name, or with a `Domain` the responding host does not belong to.
24
+ */
25
+ export function parseSetCookie(
26
+ line: string,
27
+ url: string,
28
+ now: number = Date.now(),
29
+ ): CookieInit | undefined {
30
+ const [pair = "", ...attributes] = line.split(";");
31
+ const eq = pair.indexOf("=");
32
+ const name = eq < 0 ? "" : pair.slice(0, eq).trim();
33
+ if (name === "") return undefined;
34
+ const target = new URL(url);
35
+ let domain = target.hostname;
36
+ let path = defaultPath(target.pathname);
37
+ let expires: number | undefined;
38
+ let maxAge: number | undefined;
39
+ let httpOnly = false;
40
+ let secure = false;
41
+ let sameSite: CookieInit["sameSite"];
42
+ for (const attribute of attributes) {
43
+ const at = attribute.indexOf("=");
44
+ const key = (at < 0 ? attribute : attribute.slice(0, at))
45
+ .trim()
46
+ .toLowerCase();
47
+ const value = at < 0 ? "" : attribute.slice(at + 1).trim();
48
+ if (key === "domain" && value !== "") {
49
+ const covered = value.replace(/^\./, "").toLowerCase();
50
+ const host = target.hostname.toLowerCase();
51
+ // A server may not set a cookie for a site it is not part of.
52
+ if (host !== covered && !host.endsWith(`.${covered}`)) return undefined;
53
+ domain = `.${covered}`;
54
+ } else if (key === "path" && value.startsWith("/")) path = value;
55
+ // A date names its month; a bare number is not one, though
56
+ // `Date.parse` would take "1" for the year 2001.
57
+ else if (
58
+ key === "expires" &&
59
+ /[a-z]{3}/i.test(value) &&
60
+ !Number.isNaN(Date.parse(value))
61
+ )
62
+ expires = Math.floor(Date.parse(value) / 1000);
63
+ else if (key === "max-age" && /^-?\d+$/.test(value)) maxAge = Number(value);
64
+ else if (key === "httponly") httpOnly = true;
65
+ else if (key === "secure") secure = true;
66
+ else if (key === "samesite") sameSite = sameSiteOf(value) ?? sameSite;
67
+ }
68
+ const wanted =
69
+ maxAge === undefined ? expires : Math.floor(now / 1000) + maxAge;
70
+ // A context takes a positive timestamp only: one second past the epoch
71
+ // is "long expired", which is how a server deletes a cookie.
72
+ const until =
73
+ wanted === undefined
74
+ ? undefined
75
+ : Math.min(Math.max(wanted, 1), MAX_EXPIRES);
76
+ return {
77
+ name,
78
+ value: pair.slice(eq + 1).trim(),
79
+ domain,
80
+ path,
81
+ ...(until === undefined ? {} : { expires: until }),
82
+ httpOnly,
83
+ secure,
84
+ ...(sameSite === undefined ? {} : { sameSite }),
85
+ };
86
+ }
87
+
88
+ function sameSiteOf(value: string): CookieInit["sameSite"] {
89
+ switch (value.toLowerCase()) {
90
+ case "strict":
91
+ return "Strict";
92
+ case "lax":
93
+ return "Lax";
94
+ case "none":
95
+ return "None";
96
+ default:
97
+ return undefined;
98
+ }
99
+ }
100
+
101
+ /** RFC 6265 §5.1.4: the request path up to, and not including, its last "/". */
102
+ function defaultPath(pathname: string): string {
103
+ const last = pathname.lastIndexOf("/");
104
+ return last <= 0 ? "/" : pathname.slice(0, last);
105
+ }
@@ -0,0 +1,133 @@
1
+ import { concatBytes, utf8 } from "../bytes/index.js";
2
+
3
+ /**
4
+ * The length-prefixed message framing that gRPC, gRPC-web and Connect
5
+ * streaming share: one flag byte, a 4-byte big-endian length, the payload.
6
+ *
7
+ * Every hand-written gRPC-web stub ends up re-deriving this; getting the
8
+ * trailer bit or the length endianness wrong produces a response the client
9
+ * rejects with an error that names neither.
10
+ */
11
+ export const EnvelopeFlag = {
12
+ /** gRPC / gRPC-web / Connect: the payload is compressed. */
13
+ compressed: 0b0000_0001,
14
+ /** Connect streaming: the payload is the end-of-stream JSON. */
15
+ endStream: 0b0000_0010,
16
+ /** gRPC-web: the payload is the trailer block, not a message. */
17
+ trailer: 0b1000_0000,
18
+ } as const;
19
+
20
+ export interface Envelope {
21
+ readonly flags: number;
22
+ readonly data: Uint8Array;
23
+ }
24
+
25
+ const HEADER = 5;
26
+
27
+ export function encodeEnvelope(flags: number, data: Uint8Array): Uint8Array {
28
+ const out = new Uint8Array(HEADER + data.byteLength);
29
+ out[0] = flags;
30
+ new DataView(out.buffer).setUint32(1, data.byteLength, false);
31
+ out.set(data, HEADER);
32
+ return out;
33
+ }
34
+
35
+ export function encodeEnvelopes(envelopes: readonly Envelope[]): Uint8Array {
36
+ return concatBytes(envelopes.map((e) => encodeEnvelope(e.flags, e.data)));
37
+ }
38
+
39
+ export interface EnvelopeReader {
40
+ /** Feed bytes; returns every envelope they complete, in order. */
41
+ push(chunk: Uint8Array): Envelope[];
42
+ /** Bytes held back because they do not complete an envelope yet. */
43
+ readonly buffered: number;
44
+ }
45
+
46
+ /**
47
+ * Incremental reader for a byte stream that may split an envelope anywhere,
48
+ * including inside the 5-byte header — which is exactly how HTTP chunking
49
+ * delivers a long server stream.
50
+ *
51
+ * Chunks that do not complete an envelope are kept as they came and joined
52
+ * only once it is complete, so a large message arriving in small chunks is
53
+ * copied once, not once per chunk.
54
+ */
55
+ export function createEnvelopeReader(): EnvelopeReader {
56
+ let pending: Uint8Array[] = [];
57
+ let buffered = 0;
58
+
59
+ /** Whether the pending chunks hold at least one whole envelope. */
60
+ const complete = (): boolean => {
61
+ if (buffered < HEADER) return false;
62
+ // The header may itself straddle chunks: gather just those five bytes.
63
+ const header = new Uint8Array(HEADER);
64
+ let filled = 0;
65
+ for (const chunk of pending) {
66
+ const part = chunk.subarray(0, HEADER - filled);
67
+ header.set(part, filled);
68
+ filled += part.byteLength;
69
+ if (filled === HEADER) break;
70
+ }
71
+ const length = new DataView(header.buffer).getUint32(1, false);
72
+ return buffered >= HEADER + length;
73
+ };
74
+
75
+ return {
76
+ push(chunk) {
77
+ pending.push(chunk);
78
+ buffered += chunk.byteLength;
79
+ if (!complete()) return [];
80
+ const bytes = concatBytes(pending);
81
+ const out: Envelope[] = [];
82
+ let offset = 0;
83
+ while (bytes.byteLength - offset >= HEADER) {
84
+ const view = new DataView(
85
+ bytes.buffer,
86
+ bytes.byteOffset + offset,
87
+ HEADER,
88
+ );
89
+ const length = view.getUint32(1, false);
90
+ if (bytes.byteLength - offset - HEADER < length) break;
91
+ out.push({
92
+ flags: view.getUint8(0),
93
+ data: bytes.subarray(offset + HEADER, offset + HEADER + length),
94
+ });
95
+ offset += HEADER + length;
96
+ }
97
+ const rest = bytes.subarray(offset);
98
+ pending = rest.byteLength === 0 ? [] : [rest];
99
+ buffered = rest.byteLength;
100
+ return out;
101
+ },
102
+ get buffered() {
103
+ return buffered;
104
+ },
105
+ };
106
+ }
107
+
108
+ /** Decode a complete body. `rest` holds a truncated tail, if any. */
109
+ export function decodeEnvelopes(bytes: Uint8Array): {
110
+ readonly envelopes: Envelope[];
111
+ readonly rest: number;
112
+ } {
113
+ const reader = createEnvelopeReader();
114
+ const envelopes = reader.push(bytes);
115
+ return { envelopes, rest: reader.buffered };
116
+ }
117
+
118
+ /**
119
+ * Parse a gRPC-web trailer block (`name: value\r\n` lines). Names are
120
+ * lower-cased; HTTP/1.1 header names are case-insensitive and gRPC-web
121
+ * servers disagree on the spelling.
122
+ */
123
+ export function parseTrailerBlock(data: Uint8Array): Record<string, string> {
124
+ const out: Record<string, string> = {};
125
+ for (const line of utf8(data).split(/\r?\n/)) {
126
+ const colon = line.indexOf(":");
127
+ if (colon <= 0) continue;
128
+ out[line.slice(0, colon).trim().toLowerCase()] = line
129
+ .slice(colon + 1)
130
+ .trim();
131
+ }
132
+ return out;
133
+ }
@@ -0,0 +1,9 @@
1
+ export type { Envelope, EnvelopeReader } from "./envelope.js";
2
+ export {
3
+ createEnvelopeReader,
4
+ decodeEnvelopes,
5
+ EnvelopeFlag,
6
+ encodeEnvelope,
7
+ encodeEnvelopes,
8
+ parseTrailerBlock,
9
+ } from "./envelope.js";