@heojeongbo/wirestage 0.1.0 → 0.2.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 (65) hide show
  1. package/dist/entities/plugin/model/http.d.ts +12 -3
  2. package/dist/entities/plugin/model/http.d.ts.map +1 -1
  3. package/dist/entities/plugin/model/socket.d.ts +12 -7
  4. package/dist/entities/plugin/model/socket.d.ts.map +1 -1
  5. package/dist/entities/plugin/model/stream.d.ts +7 -4
  6. package/dist/entities/plugin/model/stream.d.ts.map +1 -1
  7. package/dist/features/sse/lib/create-sse.d.ts.map +1 -1
  8. package/dist/features/sse/lib/create-sse.js +2 -1
  9. package/dist/features/sse/lib/create-sse.js.map +1 -1
  10. package/dist/features/sse/model/types.d.ts +8 -2
  11. package/dist/features/sse/model/types.d.ts.map +1 -1
  12. package/dist/features/websocket/lib/proxy.d.ts.map +1 -1
  13. package/dist/features/websocket/lib/proxy.js +16 -3
  14. package/dist/features/websocket/lib/proxy.js.map +1 -1
  15. package/dist/features/websocket/model/types.d.ts +5 -1
  16. package/dist/features/websocket/model/types.d.ts.map +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/shared/api/playwright/ports.d.ts +10 -1
  21. package/dist/shared/api/playwright/ports.d.ts.map +1 -1
  22. package/dist/shared/api/stream-server/stream-server.d.ts +3 -1
  23. package/dist/shared/api/stream-server/stream-server.d.ts.map +1 -1
  24. package/dist/shared/api/stream-server/stream-server.js +10 -3
  25. package/dist/shared/api/stream-server/stream-server.js.map +1 -1
  26. package/dist/widgets/stage/index.d.ts +1 -1
  27. package/dist/widgets/stage/index.d.ts.map +1 -1
  28. package/dist/widgets/stage/lib/create-stage.d.ts.map +1 -1
  29. package/dist/widgets/stage/lib/create-stage.js +4 -0
  30. package/dist/widgets/stage/lib/create-stage.js.map +1 -1
  31. package/dist/widgets/stage/lib/http-router.d.ts +11 -2
  32. package/dist/widgets/stage/lib/http-router.d.ts.map +1 -1
  33. package/dist/widgets/stage/lib/http-router.js +317 -76
  34. package/dist/widgets/stage/lib/http-router.js.map +1 -1
  35. package/dist/widgets/stage/lib/reads.d.ts +4 -1
  36. package/dist/widgets/stage/lib/reads.d.ts.map +1 -1
  37. package/dist/widgets/stage/lib/reads.js +32 -1
  38. package/dist/widgets/stage/lib/reads.js.map +1 -1
  39. package/dist/widgets/stage/lib/response-stream.d.ts +17 -3
  40. package/dist/widgets/stage/lib/response-stream.d.ts.map +1 -1
  41. package/dist/widgets/stage/lib/response-stream.js +88 -36
  42. package/dist/widgets/stage/lib/response-stream.js.map +1 -1
  43. package/dist/widgets/stage/lib/socket-router.d.ts.map +1 -1
  44. package/dist/widgets/stage/lib/socket-router.js +44 -15
  45. package/dist/widgets/stage/lib/socket-router.js.map +1 -1
  46. package/dist/widgets/stage/model/stage.d.ts +40 -7
  47. package/dist/widgets/stage/model/stage.d.ts.map +1 -1
  48. package/package.json +1 -1
  49. package/src/entities/plugin/model/http.ts +12 -3
  50. package/src/entities/plugin/model/socket.ts +12 -7
  51. package/src/entities/plugin/model/stream.ts +7 -4
  52. package/src/features/sse/lib/create-sse.ts +2 -1
  53. package/src/features/sse/model/types.ts +8 -2
  54. package/src/features/websocket/lib/proxy.ts +15 -3
  55. package/src/features/websocket/model/types.ts +5 -1
  56. package/src/index.ts +2 -0
  57. package/src/shared/api/playwright/ports.ts +7 -2
  58. package/src/shared/api/stream-server/stream-server.ts +11 -3
  59. package/src/widgets/stage/index.ts +2 -0
  60. package/src/widgets/stage/lib/create-stage.ts +4 -0
  61. package/src/widgets/stage/lib/http-router.ts +425 -91
  62. package/src/widgets/stage/lib/reads.ts +44 -2
  63. package/src/widgets/stage/lib/response-stream.ts +110 -37
  64. package/src/widgets/stage/lib/socket-router.ts +45 -16
  65. package/src/widgets/stage/model/stage.ts +42 -7
@@ -29,17 +29,48 @@ export function createReads(deps) {
29
29
  await sync();
30
30
  return drainCursor.take(filter);
31
31
  },
32
- async mark(name, meta) {
32
+ async mark(name, options = {}) {
33
33
  await sync();
34
+ const { page, meta } = options;
34
35
  return timeline.append({
35
36
  protocol: "wirestage",
36
37
  kind: "marker",
37
38
  direction: "none",
38
39
  endpoint: name,
39
40
  source: "test",
41
+ ...(page === undefined
42
+ ? {}
43
+ : { page: typeof page === "string" ? page : deps.pageId(page) }),
40
44
  ...(meta === undefined ? {} : { meta }),
41
45
  });
42
46
  },
47
+ cursor(base = {}) {
48
+ let position = 0;
49
+ const read = async (filter) => {
50
+ await sync();
51
+ const where = filter.where;
52
+ return timeline.frames({
53
+ ...base,
54
+ ...filter,
55
+ after: Math.max(position, base.after ?? 0, filter.after ?? 0),
56
+ where: (frame) => (base.where === undefined || base.where(frame)) &&
57
+ (where === undefined || where(frame)),
58
+ });
59
+ };
60
+ return {
61
+ async take(filter = {}) {
62
+ const frames = await read(filter);
63
+ // Past everything that arrived, not just what matched: the next
64
+ // take starts where this one looked.
65
+ position = Math.max(position, timeline.last()?.seq ?? 0);
66
+ return frames;
67
+ },
68
+ peek: (filter = {}) => read(filter),
69
+ get position() {
70
+ return position;
71
+ },
72
+ };
73
+ },
43
74
  async since(marker, filter) {
44
75
  await sync();
45
76
  const after = requireMarker(marker).seq;
@@ -1 +1 @@
1
- {"version":3,"file":"reads.js","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/reads.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reads.js","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/reads.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,23 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
- import type { ResponseStream } from "../../../entities/plugin/index.js";
2
+ import type { ResponseStream, StreamEnd } from "../../../entities/plugin/index.js";
3
+ /** A stream as the stage serves it: the rule's end of it, and the stage's. */
4
+ export interface ServedStream {
5
+ /** What the rule writes. */
6
+ readonly stream: ResponseStream;
7
+ /** The stub asked for the end, and `closed` is on its way. */
8
+ readonly closing: boolean;
9
+ /**
10
+ * The rule writing the stream failed: answer 500 with `body` while
11
+ * nothing has gone out, and cut the connection after. False when the
12
+ * response was over first — ended, cut, or let go of by the page.
13
+ */
14
+ fail(body: string): boolean;
15
+ }
3
16
  /**
4
17
  * A Node response as the stream a rule writes: the adapter between the
5
18
  * stream server's sockets and the plugin contract, which knows nothing of
6
- * Node.
19
+ * Node. `onClose` hears how the response ended before `closed` resolves, so
20
+ * whoever awaits `closed` finds the end already on record.
7
21
  */
8
- export declare function createResponseStream(request: IncomingMessage, response: ServerResponse): ResponseStream;
22
+ export declare function createResponseStream(request: IncomingMessage, response: ServerResponse, onClose: (end: StreamEnd, failed: boolean) => void): ServedStream;
9
23
  //# sourceMappingURL=response-stream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"response-stream.d.ts","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/response-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,KAAK,EACX,cAAc,EAEd,MAAM,mCAAmC,CAAC;AAK3C;;;;GAIG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,GACtB,cAAc,CA+ChB"}
1
+ {"version":3,"file":"response-stream.d.ts","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/response-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,eAAe,EAEf,cAAc,EACd,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EACX,cAAc,EACd,SAAS,EACT,MAAM,mCAAmC,CAAC;AAK3C,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC5B,4BAA4B;IAC5B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,GAChD,YAAY,CAoGd"}
@@ -4,53 +4,105 @@ import { WirestageError } from "../../../shared/lib/errors/index.js";
4
4
  /**
5
5
  * A Node response as the stream a rule writes: the adapter between the
6
6
  * stream server's sockets and the plugin contract, which knows nothing of
7
- * Node.
7
+ * Node. `onClose` hears how the response ended before `closed` resolves, so
8
+ * whoever awaits `closed` finds the end already on record.
8
9
  */
9
- export function createResponseStream(request, response) {
10
+ export function createResponseStream(request, response, onClose) {
10
11
  let state = "open";
12
+ let failed = false;
11
13
  const closed = createDeferred();
12
- response.once("close", () =>
13
- // Not ended and not cut: the page let go of it.
14
- closed.resolve(state === "open" ? "cancelled" : state));
14
+ response.once("close", () => {
15
+ // Not ended and not cut: the page let go of it.
16
+ const end = state === "open" ? "cancelled" : state;
17
+ onClose(end, failed);
18
+ closed.resolve(end);
19
+ });
20
+ /** The stream server's own headers (CORS, `connection`), before the rule's. */
21
+ const own = Object.entries(response.getHeaders());
22
+ /** Back to those: what a rule's head set is gone, what it replaced is back. */
23
+ const restore = () => {
24
+ for (const name of response.getHeaderNames())
25
+ response.removeHeader(name);
26
+ for (const [name, value] of own)
27
+ response.setHeader(name, value);
28
+ };
29
+ /**
30
+ * Whether a write can reach the page. Node drops a write — callback and
31
+ * all — into a socket destroyed or closed for writing, which is what the
32
+ * page letting go leaves, well before the response reports its close.
33
+ */
34
+ const writable = () => state === "open" && response.socket?.writable === true;
15
35
  const requestHeaders = {};
16
36
  for (const [name, value] of Object.entries(request.headers))
17
37
  requestHeaders[name] = String(value);
18
38
  return {
19
- requestHeaders,
20
- head(status, headers = {}) {
21
- response.writeHead(status, { ...headers });
22
- },
23
- flush() {
24
- response.flushHeaders();
25
- },
26
- write(chunk) {
27
- return new Promise((resolve, reject) => {
28
- if (state !== "open" || response.destroyed) {
29
- reject(new WirestageError("CLOSED", "the response stream is closed"));
30
- return;
39
+ stream: {
40
+ requestHeaders,
41
+ head(status, headers = {}) {
42
+ // Node checks a status only as the head goes out, and refused by
43
+ // `end()` it leaves the response broken: a 500 after it has no body.
44
+ if (!Number.isInteger(status) || status < 100 || status > 999)
45
+ throw new WirestageError("INVALID_ARGUMENT", `a response status is an integer from 100 to 999, got ${status}`);
46
+ // Kept off the wire until the first write or flush, so a rule that
47
+ // fails before then can still be answered with its 500.
48
+ restore();
49
+ response.statusCode = status;
50
+ for (const [name, value] of Object.entries(headers)) {
51
+ // The stream server's to say: one response per connection.
52
+ if (name.toLowerCase() === "connection")
53
+ continue;
54
+ // Several values, one per line (`set-cookie`): Node sends a
55
+ // header line for each, and refuses a value with a newline.
56
+ const values = value.split("\n");
57
+ response.setHeader(name, values.length > 1 ? values : value);
31
58
  }
32
- response.write(toBytes(chunk), (error) => error ? reject(error) : resolve());
33
- });
34
- },
35
- async end() {
36
- if (state !== "open")
37
- return;
38
- state = "ended";
39
- // A response the page already let go of never calls back from
40
- // end(): resolve on whichever comes first.
41
- if (!response.destroyed)
42
- await new Promise((resolve) => {
43
- response.once("close", resolve);
44
- response.end(resolve);
59
+ },
60
+ flush() {
61
+ response.flushHeaders();
62
+ },
63
+ write(chunk) {
64
+ return new Promise((resolve, reject) => {
65
+ if (!writable()) {
66
+ reject(new WirestageError("CLOSED", "the response stream is closed"));
67
+ return;
68
+ }
69
+ response.write(toBytes(chunk), (error) => error ? reject(error) : resolve());
45
70
  });
71
+ },
72
+ async end() {
73
+ if (writable()) {
74
+ state = "ended";
75
+ response.end();
76
+ }
77
+ await closed.promise;
78
+ },
79
+ cut() {
80
+ if (!writable())
81
+ return;
82
+ state = "cut";
83
+ response.destroy();
84
+ },
85
+ closed: closed.promise,
46
86
  },
47
- cut() {
48
- if (state !== "open")
49
- return;
50
- state = "cut";
51
- response.destroy();
87
+ get closing() {
88
+ return state !== "open" && !closed.settled;
89
+ },
90
+ fail(body) {
91
+ if (!writable())
92
+ return false;
93
+ failed = true;
94
+ if (response.headersSent) {
95
+ state = "cut";
96
+ response.destroy();
97
+ return true;
98
+ }
99
+ state = "ended";
100
+ restore();
101
+ response
102
+ .writeHead(500, { "content-type": "text/plain; charset=utf-8" })
103
+ .end(body);
104
+ return true;
52
105
  },
53
- closed: closed.promise,
54
106
  };
55
107
  }
56
108
  //# sourceMappingURL=response-stream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"response-stream.js","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/response-stream.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAErE;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CACnC,OAAwB,EACxB,QAAwB;IAExB,IAAI,KAAK,GAA6B,MAAM,CAAC;IAC7C,MAAM,MAAM,GAAG,cAAc,EAAa,CAAC;IAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;IAC3B,gDAAgD;IAChD,MAAM,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CACtD,CAAC;IACF,MAAM,cAAc,GAA2B,EAAE,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAC1D,cAAc,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO;QACN,cAAc;QACd,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,EAAE;YACxB,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK;YACJ,QAAQ,CAAC,YAAY,EAAE,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,KAAK;YACV,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC5C,IAAI,KAAK,KAAK,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;oBAC5C,MAAM,CAAC,IAAI,cAAc,CAAC,QAAQ,EAAE,+BAA+B,CAAC,CAAC,CAAC;oBACtE,OAAO;gBACR,CAAC;gBACD,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CACxC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CACjC,CAAC;YACH,CAAC,CAAC,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,GAAG;YACR,IAAI,KAAK,KAAK,MAAM;gBAAE,OAAO;YAC7B,KAAK,GAAG,OAAO,CAAC;YAChB,8DAA8D;YAC9D,2CAA2C;YAC3C,IAAI,CAAC,QAAQ,CAAC,SAAS;gBACtB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBACnC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;oBAChC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACvB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,GAAG;YACF,IAAI,KAAK,KAAK,MAAM;gBAAE,OAAO;YAC7B,KAAK,GAAG,KAAK,CAAC;YACd,QAAQ,CAAC,OAAO,EAAE,CAAC;QACpB,CAAC;QACD,MAAM,EAAE,MAAM,CAAC,OAAO;KACtB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"response-stream.js","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/response-stream.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAgBrE;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CACnC,OAAwB,EACxB,QAAwB,EACxB,OAAkD;IAElD,IAAI,KAAK,GAA6B,MAAM,CAAC;IAC7C,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,MAAM,GAAG,cAAc,EAAa,CAAC;IAC3C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;QAC3B,gDAAgD;QAChD,MAAM,GAAG,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC;QACnD,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IACH,+EAA+E;IAC/E,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAClD,+EAA+E;IAC/E,MAAM,OAAO,GAAG,GAAG,EAAE;QACpB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,cAAc,EAAE;YAAE,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1E,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG;YAC9B,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,KAA2B,CAAC,CAAC;IACxD,CAAC,CAAC;IACF;;;;OAIG;IACH,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,KAAK,KAAK,MAAM,IAAI,QAAQ,CAAC,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC9E,MAAM,cAAc,GAA2B,EAAE,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAC1D,cAAc,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO;QACN,MAAM,EAAE;YACP,cAAc;YACd,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,EAAE;gBACxB,iEAAiE;gBACjE,qEAAqE;gBACrE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG;oBAC5D,MAAM,IAAI,cAAc,CACvB,kBAAkB,EAClB,wDAAwD,MAAM,EAAE,CAChE,CAAC;gBACH,mEAAmE;gBACnE,wDAAwD;gBACxD,OAAO,EAAE,CAAC;gBACV,QAAQ,CAAC,UAAU,GAAG,MAAM,CAAC;gBAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACrD,2DAA2D;oBAC3D,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,YAAY;wBAAE,SAAS;oBAClD,4DAA4D;oBAC5D,4DAA4D;oBAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACjC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC9D,CAAC;YACF,CAAC;YACD,KAAK;gBACJ,QAAQ,CAAC,YAAY,EAAE,CAAC;YACzB,CAAC;YACD,KAAK,CAAC,KAAK;gBACV,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;oBAC5C,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;wBACjB,MAAM,CACL,IAAI,cAAc,CAAC,QAAQ,EAAE,+BAA+B,CAAC,CAC7D,CAAC;wBACF,OAAO;oBACR,CAAC;oBACD,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CACxC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CACjC,CAAC;gBACH,CAAC,CAAC,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,GAAG;gBACR,IAAI,QAAQ,EAAE,EAAE,CAAC;oBAChB,KAAK,GAAG,OAAO,CAAC;oBAChB,QAAQ,CAAC,GAAG,EAAE,CAAC;gBAChB,CAAC;gBACD,MAAM,MAAM,CAAC,OAAO,CAAC;YACtB,CAAC;YACD,GAAG;gBACF,IAAI,CAAC,QAAQ,EAAE;oBAAE,OAAO;gBACxB,KAAK,GAAG,KAAK,CAAC;gBACd,QAAQ,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;YACD,MAAM,EAAE,MAAM,CAAC,OAAO;SACtB;QACD,IAAI,OAAO;YACV,OAAO,KAAK,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAC5C,CAAC;QACD,IAAI,CAAC,IAAI;YACR,IAAI,CAAC,QAAQ,EAAE;gBAAE,OAAO,KAAK,CAAC;YAC9B,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC1B,KAAK,GAAG,KAAK,CAAC;gBACd,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,IAAI,CAAC;YACb,CAAC;YACD,KAAK,GAAG,OAAO,CAAC;YAChB,OAAO,EAAE,CAAC;YACV,QAAQ;iBACN,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,2BAA2B,EAAE,CAAC;iBAC/D,GAAG,CAAC,IAAI,CAAC,CAAC;YACZ,OAAO,IAAI,CAAC;QACb,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"socket-router.d.ts","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/socket-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAEX,YAAY,EAIZ,MAAM,mCAAmC,CAAC;AAI3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACvD,MAAM,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;CAC1C;AA8CD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,CA8L7E"}
1
+ {"version":3,"file":"socket-router.d.ts","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/socket-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAEX,YAAY,EAIZ,MAAM,mCAAmC,CAAC;AAI3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACvD,MAAM,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;CAC1C;AA8CD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,CA2N7E"}
@@ -64,19 +64,38 @@ export function createSocketRouter(deps) {
64
64
  entry.active = false;
65
65
  entries.splice(entries.indexOf(entry), 1);
66
66
  };
67
- const peer = (route, close = (options) => options) => ({
68
- send: (data) => route.send(typeof data === "string" ? data : toBuffer(data)),
69
- close: (options) => route.close(close(options)),
70
- onMessage: (handler) => route.onMessage(handler),
71
- onClose: (handler) => route.onClose(handler),
72
- });
73
67
  /**
74
- * A rule that throws is a bug in the test. Say which rule failed — in the
75
- * log, on the timeline, and in the reason the page's socket closes with —
76
- * and close both ends: the page's socket would otherwise sit open with
77
- * nobody answering it, and a server the rule connected would stay
78
- * connected. 1011 is a server's "internal error"; the server's end gets
79
- * 1000, as a script may not send 1011.
68
+ * One end, as a rule drives it. Playwright calls the rule's handlers from
69
+ * its own event dispatch, where a throw is an uncaught exception and a
70
+ * rejection an unhandled one — either surfacing in whichever test runs
71
+ * next. A handler that fails fails the rule instead, as `open` does.
72
+ */
73
+ const peer = (route, onFailure, close = (options) => options) => {
74
+ const guarded = (handler) => (...args) => {
75
+ try {
76
+ // Typed `void`, yet an async function is a valid handler.
77
+ const result = handler(...args);
78
+ if (result instanceof Promise)
79
+ result.catch(onFailure);
80
+ }
81
+ catch (error) {
82
+ void onFailure(error);
83
+ }
84
+ };
85
+ return {
86
+ send: (data) => route.send(typeof data === "string" ? data : toBuffer(data)),
87
+ close: (options) => route.close(close(options)),
88
+ onMessage: (handler) => route.onMessage(guarded(handler)),
89
+ onClose: (handler) => route.onClose(guarded(handler)),
90
+ };
91
+ };
92
+ /**
93
+ * A rule that throws, in `open` or in a handler it set, is a bug in the
94
+ * test. Say which rule failed — in the log, on the timeline, and in the
95
+ * reason the page's socket closes with — and close both ends: the page's
96
+ * socket would otherwise sit open with nobody answering it, and a server
97
+ * the rule connected would stay connected. 1011 is a server's "internal
98
+ * error"; the server's end gets 1000, as a script may not send 1011.
80
99
  */
81
100
  const fail = async (rule, view, server, error) => {
82
101
  const message = error instanceof Error ? error.message : String(error);
@@ -117,16 +136,26 @@ export function createSocketRouter(deps) {
117
136
  // the rule's own replaces.
118
137
  route.onMessage(drop);
119
138
  let server;
139
+ let failed = false;
140
+ // Once per socket, for whatever fails first. Marked before failing:
141
+ // the closes that follow are reported to the rule's handlers, and a
142
+ // broken one throws again.
143
+ const failOnce = async (error) => {
144
+ if (failed)
145
+ return;
146
+ failed = true;
147
+ await fail(entry.rule, view, server, error);
148
+ };
120
149
  const view = {
121
150
  correlation: deps.correlation(),
122
151
  url,
123
152
  context: attachment.id,
124
- page: peer(route),
153
+ page: peer(route, failOnce),
125
154
  connectToServer: () => {
126
155
  if (server === undefined) {
127
156
  const upstream = route.connectToServer();
128
157
  upstream.onMessage(drop);
129
- server = peer(upstream, forServer);
158
+ server = peer(upstream, failOnce, forServer);
130
159
  }
131
160
  return server;
132
161
  },
@@ -140,7 +169,7 @@ export function createSocketRouter(deps) {
140
169
  catch (error) {
141
170
  // Never rejected to Playwright, where it would surface as an
142
171
  // unhandled rejection in whichever test runs next.
143
- await fail(entry.rule, view, server, error);
172
+ await failOnce(error);
144
173
  }
145
174
  };
146
175
  const ensureRoute = (attachment) => {
@@ -1 +1 @@
1
- {"version":3,"file":"socket-router.js","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/socket-router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"socket-router.js","sourceRoot":"","sources":["../../../../src/widgets/stage/lib/socket-router.ts"],"names":[],"mappings":"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"}
@@ -16,9 +16,11 @@ export interface StageOptions<Plugins extends readonly AnyWirePlugin[]> {
16
16
  */
17
17
  readonly pageFlushMs?: number;
18
18
  /**
19
- * How long a page may take to answer a flush or a command before a read
20
- * goes on without it — and Playwright to take the page hooks out before a
21
- * detach goes on. Default 2000 ms.
19
+ * How long a page may take to answer a flush or a command, or the
20
+ * browser to hand over a response's body, before a read goes on without
21
+ * it; how long a live stream's request may take to reach the stream
22
+ * server before the stream is given up; and how long Playwright may take
23
+ * to take the page hooks out before a detach goes on. Default 2000 ms.
22
24
  */
23
25
  readonly pageTimeoutMs?: number;
24
26
  /** TLS for live streams on https pages, and the bind host. */
@@ -36,6 +38,32 @@ export interface StageReport {
36
38
  readonly snapshot: TimelineSnapshot;
37
39
  readonly text: string;
38
40
  }
41
+ export interface MarkOptions {
42
+ /**
43
+ * The page the marker is about. The marker carries its id, so a read
44
+ * narrowed to that page (`{ page }`) includes it.
45
+ */
46
+ readonly page?: PagePort | string;
47
+ /** Anything else worth keeping on the marker. */
48
+ readonly meta?: Readonly<Record<string, unknown>>;
49
+ }
50
+ /**
51
+ * A reading position of its own on the timeline: what a helper that keeps a
52
+ * log per page, per channel or per check reads from, without moving the
53
+ * stage's `drain` or another cursor.
54
+ */
55
+ export interface StageCursor {
56
+ /**
57
+ * Bring the timeline up to date, then take what reached it since this
58
+ * cursor last took — narrowed by the cursor's filter and `filter` — and
59
+ * move past all of it, matching or not.
60
+ */
61
+ take(filter?: FrameFilter): Promise<Frame[]>;
62
+ /** The same frames as `take`, without moving. */
63
+ peek(filter?: FrameFilter): Promise<Frame[]>;
64
+ /** The `seq` the cursor has read up to; 0 before its first take. */
65
+ readonly position: number;
66
+ }
39
67
  export interface ReportOptions {
40
68
  /** Frames kept, counting back from the newest. Default 1,000. */
41
69
  readonly limit?: number;
@@ -58,16 +86,21 @@ export interface StageCore {
58
86
  /** The id frames use for this page. */
59
87
  pageId(page: PagePort): string;
60
88
  /**
61
- * Bring the timeline up to date: flush every page's buffer and wait for
62
- * the responses already back from the network. The reads below do it for
63
- * you.
89
+ * Bring the timeline up to date: flush every page's buffer, and wait for
90
+ * the responses already back from the network and the ends of the
91
+ * streams a stub closed. The reads below do it for you.
64
92
  */
65
93
  sync(): Promise<void>;
66
94
  frames(filter?: FrameFilter): Promise<Frame[]>;
67
95
  /** Frames since the previous `drain` (any filter), narrowed by `filter`. */
68
96
  drain(filter?: FrameFilter): Promise<Frame[]>;
69
97
  /** Put a named marker on the timeline, after everything that happened so far. */
70
- mark(name: string, meta?: Readonly<Record<string, unknown>>): Promise<Frame>;
98
+ mark(name: string, options?: MarkOptions): Promise<Frame>;
99
+ /**
100
+ * A cursor of its own, from the start of the timeline: every `take`
101
+ * returns what is new since the previous one.
102
+ */
103
+ cursor(filter?: FrameFilter): StageCursor;
71
104
  /** Frames after the most recent marker called `marker`. */
72
105
  since(marker: string, filter?: FrameFilter): Promise<Frame[]>;
73
106
  /** Frames between two markers, exclusive. */
@@ -1 +1 @@
1
- {"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../../../src/widgets/stage/model/stage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../../../src/widgets/stage/model/stage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heojeongbo/wirestage",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Record, fake and fault-inject browser wire traffic in Playwright: REST, Connect, gRPC-web, gRPC, SSE, WebSocket and WebRTC data channels on one timeline.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -49,7 +49,10 @@ export type AbortErrorCode =
49
49
  export type HttpOutcome =
50
50
  /**
51
51
  * Answer with a complete response. A header may carry several values
52
- * separated by a newline (`set-cookie`).
52
+ * separated by a newline: `set-cookie` is sent as a header line each,
53
+ * any other header as one value, `, `-separated. A header Chromium
54
+ * would refuse — a name that is not a token, a CR or NUL in a value — is
55
+ * the rule's error.
53
56
  */
54
57
  | {
55
58
  readonly type: "fulfill";
@@ -61,13 +64,19 @@ export type HttpOutcome =
61
64
  * Answer with a response that stays open (server streams, SSE): `open`
62
65
  * gets the stream to write. The request is redirected to the stage's
63
66
  * local stream server, which `route.fulfill` cannot stand in for because
64
- * it takes the whole body at once.
67
+ * it takes the whole body at once. An `open` that throws is the rule's
68
+ * error, as a throwing `handle` is: the page gets the 500 while nothing
69
+ * has gone out, and a cut connection after.
65
70
  */
66
71
  | {
67
72
  readonly type: "stream";
68
73
  open(stream: ResponseStream): void | Promise<void>;
69
74
  }
70
- /** Send to the network, optionally rewritten. Lower rules are skipped. */
75
+ /**
76
+ * Send to the network, optionally rewritten. Lower rules are skipped.
77
+ * `url` may be relative to the request's, and keeps its scheme:
78
+ * Playwright rewrites a URL within its scheme only.
79
+ */
71
80
  | {
72
81
  readonly type: "continue";
73
82
  readonly url?: string;
@@ -19,6 +19,8 @@ export interface SocketPeer {
19
19
  /**
20
20
  * Messages this end sends. One handler; a later call replaces it. Until
21
21
  * one is set, what this end sends is dropped, not passed on to the other.
22
+ * A handler that throws, or rejects, fails the rule (see
23
+ * `SocketRule.open`).
22
24
  */
23
25
  onMessage(handler: (data: string | Uint8Array) => void): void;
24
26
  /**
@@ -26,7 +28,8 @@ export interface SocketPeer {
26
28
  * the page starts is reported again once `close()` completes it, so a
27
29
  * handler must expect to run twice. Setting one turns off the automatic
28
30
  * forwarding of a close to the other end: the page's socket then hangs in
29
- * CLOSING until the handler closes the page's end itself.
31
+ * CLOSING until the handler closes the page's end itself. A handler that
32
+ * throws, or rejects, fails the rule.
30
33
  */
31
34
  onClose(
32
35
  handler: (code: number | undefined, reason: string | undefined) => void,
@@ -70,12 +73,14 @@ export interface SocketRule {
70
73
  * the handlers before awaiting anything: an end drops what it sends
71
74
  * until it has one.
72
75
  *
73
- * A rule that throws, or rejects, is a bug in the test: the stage logs
74
- * it, records a `fault` frame (`meta.reason` `rule-error`, `meta.rule`
75
- * the label, `meta.error` the message) and closes the page's end with
76
- * 1011 and a reason naming the rule — and the server's end too, if the
77
- * rule connected it. The ends' `onClose` handlers hear those closes as
78
- * they hear any other.
76
+ * A rule that throws, or rejects — here, or in a handler it set on
77
+ * either end — is a bug in the test: the stage logs it, records a
78
+ * `fault` frame (`meta.reason` `rule-error`, `meta.rule` the label,
79
+ * `meta.error` the message) and closes the page's end with 1011 and a
80
+ * reason naming the rule — and the server's end too, if the rule
81
+ * connected it. Once per socket: what fails after that is not reported
82
+ * again. The ends' `onClose` handlers hear those closes as they hear any
83
+ * other.
79
84
  */
80
85
  open(socket: SocketView): void | Promise<void>;
81
86
  }
@@ -21,23 +21,26 @@ export interface ResponseStream {
21
21
  readonly requestHeaders: Readonly<Record<string, string>>;
22
22
  /**
23
23
  * Set the status and headers. They go out with the first `write`, or at
24
- * once on `flush`. Without a call the response is a bare 200.
24
+ * once on `flush`, and a later call replaces them until then. Without a
25
+ * call the response is a bare 200. A header may carry several values
26
+ * separated by a newline (`set-cookie`). `connection` is the stream
27
+ * server's: it closes every connection after one response.
25
28
  */
26
29
  head(status: number, headers?: Readonly<Record<string, string>>): void;
27
30
  /** Send the head now, before any body: an EventSource opens on it. */
28
31
  flush(): void;
29
32
  /**
30
33
  * Write a chunk. Resolves once it is handed to the socket; rejects with
31
- * `CLOSED` when the response is over.
34
+ * `CLOSED` when the response is over, the page letting go included.
32
35
  */
33
36
  write(chunk: Uint8Array | string): Promise<void>;
34
- /** End the response cleanly. Resolves once it is closed. */
37
+ /** End the response cleanly. Resolves once it is closed, as `closed` does. */
35
38
  end(): Promise<void>;
36
39
  /**
37
40
  * Reset the connection mid-response: no terminator, no trailer — what a
38
41
  * network drop looks like to the page.
39
42
  */
40
43
  cut(): void;
41
- /** Resolves when the response is over, with how. */
44
+ /** Resolves when the response is over, with how, once that is on the timeline. */
42
45
  readonly closed: Promise<StreamEnd>;
43
46
  }
@@ -52,7 +52,6 @@ export function sse(): WirePlugin<"sse", SseApi> {
52
52
  stream.head(streamOptions.status ?? 200, {
53
53
  "content-type": "text/event-stream; charset=utf-8",
54
54
  "cache-control": "no-cache",
55
- connection: "keep-alive",
56
55
  ...streamOptions.headers,
57
56
  });
58
57
  // An EventSource opens on the headers, before any event.
@@ -84,6 +83,8 @@ export function sse(): WirePlugin<"sse", SseApi> {
84
83
  end: () => stream.end(),
85
84
  async cut() {
86
85
  stream.cut();
86
+ // The stage records the end before `closed` resolves.
87
+ await stream.closed;
87
88
  },
88
89
  closed: stream.closed,
89
90
  };