@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.
- package/LICENSE +21 -0
- package/LICENSES.md +21 -0
- package/README.md +150 -2
- package/dist/app/playwright/index.d.ts +3 -0
- package/dist/app/playwright/index.d.ts.map +1 -0
- package/dist/app/playwright/index.js +2 -0
- package/dist/app/playwright/index.js.map +1 -0
- package/dist/app/playwright/lib/fixture.d.ts +61 -0
- package/dist/app/playwright/lib/fixture.d.ts.map +1 -0
- package/dist/app/playwright/lib/fixture.js +110 -0
- package/dist/app/playwright/lib/fixture.js.map +1 -0
- package/dist/connect.d.ts +7 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +7 -0
- package/dist/connect.js.map +1 -0
- package/dist/entities/frame/@x/plugin.d.ts +9 -0
- package/dist/entities/frame/@x/plugin.d.ts.map +1 -0
- package/dist/entities/frame/@x/plugin.js +2 -0
- package/dist/entities/frame/@x/plugin.js.map +1 -0
- package/dist/entities/frame/index.d.ts +6 -0
- package/dist/entities/frame/index.d.ts.map +1 -0
- package/dist/entities/frame/index.js +4 -0
- package/dist/entities/frame/index.js.map +1 -0
- package/dist/entities/frame/lib/filter.d.ts +8 -0
- package/dist/entities/frame/lib/filter.d.ts.map +1 -0
- package/dist/entities/frame/lib/filter.js +62 -0
- package/dist/entities/frame/lib/filter.js.map +1 -0
- package/dist/entities/frame/lib/payload.d.ts +8 -0
- package/dist/entities/frame/lib/payload.d.ts.map +1 -0
- package/dist/entities/frame/lib/payload.js +42 -0
- package/dist/entities/frame/lib/payload.js.map +1 -0
- package/dist/entities/frame/lib/snapshot.d.ts +15 -0
- package/dist/entities/frame/lib/snapshot.d.ts.map +1 -0
- package/dist/entities/frame/lib/snapshot.js +90 -0
- package/dist/entities/frame/lib/snapshot.js.map +1 -0
- package/dist/entities/frame/lib/timeline.d.ts +23 -0
- package/dist/entities/frame/lib/timeline.d.ts.map +1 -0
- package/dist/entities/frame/lib/timeline.js +122 -0
- package/dist/entities/frame/lib/timeline.js.map +1 -0
- package/dist/entities/frame/model/frame.d.ts +182 -0
- package/dist/entities/frame/model/frame.d.ts.map +1 -0
- package/dist/entities/frame/model/frame.js +2 -0
- package/dist/entities/frame/model/frame.js.map +1 -0
- package/dist/entities/plugin/index.d.ts +9 -0
- package/dist/entities/plugin/index.d.ts.map +1 -0
- package/dist/entities/plugin/index.js +3 -0
- package/dist/entities/plugin/index.js.map +1 -0
- package/dist/entities/plugin/lib/define-plugin.d.ts +8 -0
- package/dist/entities/plugin/lib/define-plugin.d.ts.map +1 -0
- package/dist/entities/plugin/lib/define-plugin.js +9 -0
- package/dist/entities/plugin/lib/define-plugin.js.map +1 -0
- package/dist/entities/plugin/lib/named.d.ts +10 -0
- package/dist/entities/plugin/lib/named.d.ts.map +1 -0
- package/dist/entities/plugin/lib/named.js +17 -0
- package/dist/entities/plugin/lib/named.js.map +1 -0
- package/dist/entities/plugin/model/attachment.d.ts +18 -0
- package/dist/entities/plugin/model/attachment.d.ts.map +1 -0
- package/dist/entities/plugin/model/attachment.js +2 -0
- package/dist/entities/plugin/model/attachment.js.map +1 -0
- package/dist/entities/plugin/model/http.d.ts +126 -0
- package/dist/entities/plugin/model/http.d.ts.map +1 -0
- package/dist/entities/plugin/model/http.js +2 -0
- package/dist/entities/plugin/model/http.js.map +1 -0
- package/dist/entities/plugin/model/page.d.ts +100 -0
- package/dist/entities/plugin/model/page.d.ts.map +1 -0
- package/dist/entities/plugin/model/page.js +2 -0
- package/dist/entities/plugin/model/page.js.map +1 -0
- package/dist/entities/plugin/model/plugin.d.ts +83 -0
- package/dist/entities/plugin/model/plugin.d.ts.map +1 -0
- package/dist/entities/plugin/model/plugin.js +2 -0
- package/dist/entities/plugin/model/plugin.js.map +1 -0
- package/dist/entities/plugin/model/socket.d.ts +102 -0
- package/dist/entities/plugin/model/socket.d.ts.map +1 -0
- package/dist/entities/plugin/model/socket.js +2 -0
- package/dist/entities/plugin/model/socket.js.map +1 -0
- package/dist/entities/plugin/model/stream.d.ts +43 -0
- package/dist/entities/plugin/model/stream.d.ts.map +1 -0
- package/dist/entities/plugin/model/stream.js +2 -0
- package/dist/entities/plugin/model/stream.js.map +1 -0
- package/dist/features/connect/index.d.ts +5 -0
- package/dist/features/connect/index.d.ts.map +1 -0
- package/dist/features/connect/index.js +4 -0
- package/dist/features/connect/index.js.map +1 -0
- package/dist/features/connect/lib/calls.d.ts +9 -0
- package/dist/features/connect/lib/calls.d.ts.map +1 -0
- package/dist/features/connect/lib/calls.js +46 -0
- package/dist/features/connect/lib/calls.js.map +1 -0
- package/dist/features/connect/lib/client.d.ts +33 -0
- package/dist/features/connect/lib/client.d.ts.map +1 -0
- package/dist/features/connect/lib/client.js +147 -0
- package/dist/features/connect/lib/client.js.map +1 -0
- package/dist/features/connect/lib/create-connect.d.ts +14 -0
- package/dist/features/connect/lib/create-connect.d.ts.map +1 -0
- package/dist/features/connect/lib/create-connect.js +124 -0
- package/dist/features/connect/lib/create-connect.js.map +1 -0
- package/dist/features/connect/lib/faults.d.ts +18 -0
- package/dist/features/connect/lib/faults.d.ts.map +1 -0
- package/dist/features/connect/lib/faults.js +85 -0
- package/dist/features/connect/lib/faults.js.map +1 -0
- package/dist/features/connect/lib/protocol.d.ts +42 -0
- package/dist/features/connect/lib/protocol.d.ts.map +1 -0
- package/dist/features/connect/lib/protocol.js +228 -0
- package/dist/features/connect/lib/protocol.js.map +1 -0
- package/dist/features/connect/lib/record.d.ts +14 -0
- package/dist/features/connect/lib/record.d.ts.map +1 -0
- package/dist/features/connect/lib/record.js +36 -0
- package/dist/features/connect/lib/record.js.map +1 -0
- package/dist/features/connect/lib/recorder.d.ts +77 -0
- package/dist/features/connect/lib/recorder.d.ts.map +1 -0
- package/dist/features/connect/lib/recorder.js +209 -0
- package/dist/features/connect/lib/recorder.js.map +1 -0
- package/dist/features/connect/lib/rules.d.ts +51 -0
- package/dist/features/connect/lib/rules.d.ts.map +1 -0
- package/dist/features/connect/lib/rules.js +222 -0
- package/dist/features/connect/lib/rules.js.map +1 -0
- package/dist/features/connect/lib/serve.d.ts +10 -0
- package/dist/features/connect/lib/serve.d.ts.map +1 -0
- package/dist/features/connect/lib/serve.js +78 -0
- package/dist/features/connect/lib/serve.js.map +1 -0
- package/dist/features/connect/lib/status-of.d.ts +11 -0
- package/dist/features/connect/lib/status-of.d.ts.map +1 -0
- package/dist/features/connect/lib/status-of.js +22 -0
- package/dist/features/connect/lib/status-of.js.map +1 -0
- package/dist/features/connect/lib/stubs.d.ts +18 -0
- package/dist/features/connect/lib/stubs.d.ts.map +1 -0
- package/dist/features/connect/lib/stubs.js +174 -0
- package/dist/features/connect/lib/stubs.js.map +1 -0
- package/dist/features/connect/lib/universal.d.ts +19 -0
- package/dist/features/connect/lib/universal.d.ts.map +1 -0
- package/dist/features/connect/lib/universal.js +71 -0
- package/dist/features/connect/lib/universal.js.map +1 -0
- package/dist/features/connect/model/types.d.ts +247 -0
- package/dist/features/connect/model/types.d.ts.map +1 -0
- package/dist/features/connect/model/types.js +2 -0
- package/dist/features/connect/model/types.js.map +1 -0
- package/dist/features/rest/index.d.ts +5 -0
- package/dist/features/rest/index.d.ts.map +1 -0
- package/dist/features/rest/index.js +3 -0
- package/dist/features/rest/index.js.map +1 -0
- package/dist/features/rest/lib/calls.d.ts +8 -0
- package/dist/features/rest/lib/calls.d.ts.map +1 -0
- package/dist/features/rest/lib/calls.js +32 -0
- package/dist/features/rest/lib/calls.js.map +1 -0
- package/dist/features/rest/lib/create-rest.d.ts +8 -0
- package/dist/features/rest/lib/create-rest.d.ts.map +1 -0
- package/dist/features/rest/lib/create-rest.js +136 -0
- package/dist/features/rest/lib/create-rest.js.map +1 -0
- package/dist/features/rest/lib/path.d.ts +14 -0
- package/dist/features/rest/lib/path.d.ts.map +1 -0
- package/dist/features/rest/lib/path.js +58 -0
- package/dist/features/rest/lib/path.js.map +1 -0
- package/dist/features/rest/lib/reply.d.ts +25 -0
- package/dist/features/rest/lib/reply.d.ts.map +1 -0
- package/dist/features/rest/lib/reply.js +40 -0
- package/dist/features/rest/lib/reply.js.map +1 -0
- package/dist/features/rest/model/types.d.ts +74 -0
- package/dist/features/rest/model/types.d.ts.map +1 -0
- package/dist/features/rest/model/types.js +2 -0
- package/dist/features/rest/model/types.js.map +1 -0
- package/dist/features/sse/index.d.ts +4 -0
- package/dist/features/sse/index.d.ts.map +1 -0
- package/dist/features/sse/index.js +3 -0
- package/dist/features/sse/index.js.map +1 -0
- package/dist/features/sse/lib/create-sse.d.ts +9 -0
- package/dist/features/sse/lib/create-sse.d.ts.map +1 -0
- package/dist/features/sse/lib/create-sse.js +120 -0
- package/dist/features/sse/lib/create-sse.js.map +1 -0
- package/dist/features/sse/lib/encode.d.ts +8 -0
- package/dist/features/sse/lib/encode.d.ts.map +1 -0
- package/dist/features/sse/lib/encode.js +29 -0
- package/dist/features/sse/lib/encode.js.map +1 -0
- package/dist/features/sse/model/types.d.ts +62 -0
- package/dist/features/sse/model/types.d.ts.map +1 -0
- package/dist/features/sse/model/types.js +2 -0
- package/dist/features/sse/model/types.js.map +1 -0
- package/dist/features/webrtc/index.d.ts +3 -0
- package/dist/features/webrtc/index.d.ts.map +1 -0
- package/dist/features/webrtc/index.js +2 -0
- package/dist/features/webrtc/index.js.map +1 -0
- package/dist/features/webrtc/lib/create-webrtc.d.ts +9 -0
- package/dist/features/webrtc/lib/create-webrtc.d.ts.map +1 -0
- package/dist/features/webrtc/lib/create-webrtc.js +123 -0
- package/dist/features/webrtc/lib/create-webrtc.js.map +1 -0
- package/dist/features/webrtc/lib/rtc-page-module.d.ts +22 -0
- package/dist/features/webrtc/lib/rtc-page-module.d.ts.map +1 -0
- package/dist/features/webrtc/lib/rtc-page-module.js +161 -0
- package/dist/features/webrtc/lib/rtc-page-module.js.map +1 -0
- package/dist/features/webrtc/lib/to-frame.d.ts +9 -0
- package/dist/features/webrtc/lib/to-frame.d.ts.map +1 -0
- package/dist/features/webrtc/lib/to-frame.js +43 -0
- package/dist/features/webrtc/lib/to-frame.js.map +1 -0
- package/dist/features/webrtc/model/types.d.ts +70 -0
- package/dist/features/webrtc/model/types.d.ts.map +1 -0
- package/dist/features/webrtc/model/types.js +2 -0
- package/dist/features/webrtc/model/types.js.map +1 -0
- package/dist/features/websocket/index.d.ts +3 -0
- package/dist/features/websocket/index.d.ts.map +1 -0
- package/dist/features/websocket/index.js +2 -0
- package/dist/features/websocket/index.js.map +1 -0
- package/dist/features/websocket/lib/create-websocket.d.ts +9 -0
- package/dist/features/websocket/lib/create-websocket.d.ts.map +1 -0
- package/dist/features/websocket/lib/create-websocket.js +34 -0
- package/dist/features/websocket/lib/create-websocket.js.map +1 -0
- package/dist/features/websocket/lib/mock.d.ts +6 -0
- package/dist/features/websocket/lib/mock.d.ts.map +1 -0
- package/dist/features/websocket/lib/mock.js +96 -0
- package/dist/features/websocket/lib/mock.js.map +1 -0
- package/dist/features/websocket/lib/proxy.d.ts +9 -0
- package/dist/features/websocket/lib/proxy.d.ts.map +1 -0
- package/dist/features/websocket/lib/proxy.js +107 -0
- package/dist/features/websocket/lib/proxy.js.map +1 -0
- package/dist/features/websocket/lib/wire.d.ts +16 -0
- package/dist/features/websocket/lib/wire.d.ts.map +1 -0
- package/dist/features/websocket/lib/wire.js +46 -0
- package/dist/features/websocket/lib/wire.js.map +1 -0
- package/dist/features/websocket/model/types.d.ts +129 -0
- package/dist/features/websocket/model/types.d.ts.map +1 -0
- package/dist/features/websocket/model/types.js +2 -0
- package/dist/features/websocket/model/types.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/playwright.d.ts +4 -0
- package/dist/playwright.d.ts.map +1 -0
- package/dist/playwright.js +2 -0
- package/dist/playwright.js.map +1 -0
- package/dist/rest.d.ts +3 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/rest.js +3 -0
- package/dist/rest.js.map +1 -0
- package/dist/shared/api/http-server/index.d.ts +3 -0
- package/dist/shared/api/http-server/index.d.ts.map +1 -0
- package/dist/shared/api/http-server/index.js +2 -0
- package/dist/shared/api/http-server/index.js.map +1 -0
- package/dist/shared/api/http-server/listen.d.ts +25 -0
- package/dist/shared/api/http-server/listen.d.ts.map +1 -0
- package/dist/shared/api/http-server/listen.js +44 -0
- package/dist/shared/api/http-server/listen.js.map +1 -0
- package/dist/shared/api/playwright/index.d.ts +2 -0
- package/dist/shared/api/playwright/index.d.ts.map +1 -0
- package/dist/shared/api/playwright/index.js +2 -0
- package/dist/shared/api/playwright/index.js.map +1 -0
- package/dist/shared/api/playwright/ports.d.ts +117 -0
- package/dist/shared/api/playwright/ports.d.ts.map +1 -0
- package/dist/shared/api/playwright/ports.js +11 -0
- package/dist/shared/api/playwright/ports.js.map +1 -0
- package/dist/shared/api/stream-server/index.d.ts +3 -0
- package/dist/shared/api/stream-server/index.d.ts.map +1 -0
- package/dist/shared/api/stream-server/index.js +2 -0
- package/dist/shared/api/stream-server/index.js.map +1 -0
- package/dist/shared/api/stream-server/stream-server.d.ts +43 -0
- package/dist/shared/api/stream-server/stream-server.d.ts.map +1 -0
- package/dist/shared/api/stream-server/stream-server.js +160 -0
- package/dist/shared/api/stream-server/stream-server.js.map +1 -0
- package/dist/shared/lib/async/arrivals.d.ts +31 -0
- package/dist/shared/lib/async/arrivals.d.ts.map +1 -0
- package/dist/shared/lib/async/arrivals.js +57 -0
- package/dist/shared/lib/async/arrivals.js.map +1 -0
- package/dist/shared/lib/async/async-queue.d.ts +23 -0
- package/dist/shared/lib/async/async-queue.d.ts.map +1 -0
- package/dist/shared/lib/async/async-queue.js +80 -0
- package/dist/shared/lib/async/async-queue.js.map +1 -0
- package/dist/shared/lib/async/deferred.d.ts +12 -0
- package/dist/shared/lib/async/deferred.d.ts.map +1 -0
- package/dist/shared/lib/async/deferred.js +34 -0
- package/dist/shared/lib/async/deferred.js.map +1 -0
- package/dist/shared/lib/async/index.d.ts +8 -0
- package/dist/shared/lib/async/index.d.ts.map +1 -0
- package/dist/shared/lib/async/index.js +5 -0
- package/dist/shared/lib/async/index.js.map +1 -0
- package/dist/shared/lib/async/run-all.d.ts +8 -0
- package/dist/shared/lib/async/run-all.d.ts.map +1 -0
- package/dist/shared/lib/async/run-all.js +22 -0
- package/dist/shared/lib/async/run-all.js.map +1 -0
- package/dist/shared/lib/bytes/bytes.d.ts +18 -0
- package/dist/shared/lib/bytes/bytes.d.ts.map +1 -0
- package/dist/shared/lib/bytes/bytes.js +48 -0
- package/dist/shared/lib/bytes/bytes.js.map +1 -0
- package/dist/shared/lib/bytes/index.d.ts +3 -0
- package/dist/shared/lib/bytes/index.d.ts.map +1 -0
- package/dist/shared/lib/bytes/index.js +2 -0
- package/dist/shared/lib/bytes/index.js.map +1 -0
- package/dist/shared/lib/clock/clock.d.ts +29 -0
- package/dist/shared/lib/clock/clock.d.ts.map +1 -0
- package/dist/shared/lib/clock/clock.js +85 -0
- package/dist/shared/lib/clock/clock.js.map +1 -0
- package/dist/shared/lib/clock/index.d.ts +3 -0
- package/dist/shared/lib/clock/index.d.ts.map +1 -0
- package/dist/shared/lib/clock/index.js +2 -0
- package/dist/shared/lib/clock/index.js.map +1 -0
- package/dist/shared/lib/cookies/index.d.ts +3 -0
- package/dist/shared/lib/cookies/index.d.ts.map +1 -0
- package/dist/shared/lib/cookies/index.js +2 -0
- package/dist/shared/lib/cookies/index.js.map +1 -0
- package/dist/shared/lib/cookies/set-cookie.d.ts +22 -0
- package/dist/shared/lib/cookies/set-cookie.d.ts.map +1 -0
- package/dist/shared/lib/cookies/set-cookie.js +89 -0
- package/dist/shared/lib/cookies/set-cookie.js.map +1 -0
- package/dist/shared/lib/envelope/envelope.d.ts +50 -0
- package/dist/shared/lib/envelope/envelope.d.ts.map +1 -0
- package/dist/shared/lib/envelope/envelope.js +111 -0
- package/dist/shared/lib/envelope/envelope.js.map +1 -0
- package/dist/shared/lib/envelope/index.d.ts +3 -0
- package/dist/shared/lib/envelope/index.d.ts.map +1 -0
- package/dist/shared/lib/envelope/index.js +2 -0
- package/dist/shared/lib/envelope/index.js.map +1 -0
- package/dist/shared/lib/errors/index.d.ts +3 -0
- package/dist/shared/lib/errors/index.d.ts.map +1 -0
- package/dist/shared/lib/errors/index.js +2 -0
- package/dist/shared/lib/errors/index.js.map +1 -0
- package/dist/shared/lib/errors/wirestage-error.d.ts +28 -0
- package/dist/shared/lib/errors/wirestage-error.d.ts.map +1 -0
- package/dist/shared/lib/errors/wirestage-error.js +16 -0
- package/dist/shared/lib/errors/wirestage-error.js.map +1 -0
- package/dist/shared/lib/id/id.d.ts +10 -0
- package/dist/shared/lib/id/id.d.ts.map +1 -0
- package/dist/shared/lib/id/id.js +26 -0
- package/dist/shared/lib/id/id.js.map +1 -0
- package/dist/shared/lib/id/index.d.ts +2 -0
- package/dist/shared/lib/id/index.d.ts.map +1 -0
- package/dist/shared/lib/id/index.js +2 -0
- package/dist/shared/lib/id/index.js.map +1 -0
- package/dist/shared/lib/logger/index.d.ts +3 -0
- package/dist/shared/lib/logger/index.d.ts.map +1 -0
- package/dist/shared/lib/logger/index.js +2 -0
- package/dist/shared/lib/logger/index.js.map +1 -0
- package/dist/shared/lib/logger/logger.d.ts +46 -0
- package/dist/shared/lib/logger/logger.d.ts.map +1 -0
- package/dist/shared/lib/logger/logger.js +67 -0
- package/dist/shared/lib/logger/logger.js.map +1 -0
- package/dist/shared/lib/match/index.d.ts +3 -0
- package/dist/shared/lib/match/index.d.ts.map +1 -0
- package/dist/shared/lib/match/index.js +2 -0
- package/dist/shared/lib/match/index.js.map +1 -0
- package/dist/shared/lib/match/url-matcher.d.ts +27 -0
- package/dist/shared/lib/match/url-matcher.d.ts.map +1 -0
- package/dist/shared/lib/match/url-matcher.js +88 -0
- package/dist/shared/lib/match/url-matcher.js.map +1 -0
- package/dist/sse.d.ts +3 -0
- package/dist/sse.d.ts.map +1 -0
- package/dist/sse.js +3 -0
- package/dist/sse.js.map +1 -0
- package/dist/webrtc.d.ts +3 -0
- package/dist/webrtc.d.ts.map +1 -0
- package/dist/webrtc.js +3 -0
- package/dist/webrtc.js.map +1 -0
- package/dist/websocket.d.ts +3 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +3 -0
- package/dist/websocket.js.map +1 -0
- package/dist/widgets/stage/index.d.ts +3 -0
- package/dist/widgets/stage/index.d.ts.map +1 -0
- package/dist/widgets/stage/index.js +2 -0
- package/dist/widgets/stage/index.js.map +1 -0
- package/dist/widgets/stage/lib/attached-context.d.ts +10 -0
- package/dist/widgets/stage/lib/attached-context.d.ts.map +1 -0
- package/dist/widgets/stage/lib/attached-context.js +2 -0
- package/dist/widgets/stage/lib/attached-context.js.map +1 -0
- package/dist/widgets/stage/lib/create-stage.d.ts +12 -0
- package/dist/widgets/stage/lib/create-stage.d.ts.map +1 -0
- package/dist/widgets/stage/lib/create-stage.js +248 -0
- package/dist/widgets/stage/lib/create-stage.js.map +1 -0
- package/dist/widgets/stage/lib/http-router.d.ts +35 -0
- package/dist/widgets/stage/lib/http-router.d.ts.map +1 -0
- package/dist/widgets/stage/lib/http-router.js +455 -0
- package/dist/widgets/stage/lib/http-router.js.map +1 -0
- package/dist/widgets/stage/lib/page-host.d.ts +36 -0
- package/dist/widgets/stage/lib/page-host.d.ts.map +1 -0
- package/dist/widgets/stage/lib/page-host.js +240 -0
- package/dist/widgets/stage/lib/page-host.js.map +1 -0
- package/dist/widgets/stage/lib/page-runtime.d.ts +93 -0
- package/dist/widgets/stage/lib/page-runtime.d.ts.map +1 -0
- package/dist/widgets/stage/lib/page-runtime.js +247 -0
- package/dist/widgets/stage/lib/page-runtime.js.map +1 -0
- package/dist/widgets/stage/lib/reads.d.ts +21 -0
- package/dist/widgets/stage/lib/reads.d.ts.map +1 -0
- package/dist/widgets/stage/lib/reads.js +97 -0
- package/dist/widgets/stage/lib/reads.js.map +1 -0
- package/dist/widgets/stage/lib/response-stream.d.ts +9 -0
- package/dist/widgets/stage/lib/response-stream.d.ts.map +1 -0
- package/dist/widgets/stage/lib/response-stream.js +56 -0
- package/dist/widgets/stage/lib/response-stream.js.map +1 -0
- package/dist/widgets/stage/lib/socket-router.d.ts +25 -0
- package/dist/widgets/stage/lib/socket-router.d.ts.map +1 -0
- package/dist/widgets/stage/lib/socket-router.js +204 -0
- package/dist/widgets/stage/lib/socket-router.js.map +1 -0
- package/dist/widgets/stage/model/stage.d.ts +86 -0
- package/dist/widgets/stage/model/stage.d.ts.map +1 -0
- package/dist/widgets/stage/model/stage.js +2 -0
- package/dist/widgets/stage/model/stage.js.map +1 -0
- package/package.json +140 -5
- package/src/app/playwright/index.ts +7 -0
- package/src/app/playwright/lib/fixture.ts +201 -0
- package/src/connect.ts +6 -0
- package/src/entities/frame/@x/plugin.ts +8 -0
- package/src/entities/frame/index.ts +19 -0
- package/src/entities/frame/lib/filter.ts +58 -0
- package/src/entities/frame/lib/payload.ts +42 -0
- package/src/entities/frame/lib/snapshot.ts +105 -0
- package/src/entities/frame/lib/timeline.ts +147 -0
- package/src/entities/frame/model/frame.ts +191 -0
- package/src/entities/plugin/index.ts +36 -0
- package/src/entities/plugin/lib/define-plugin.ts +12 -0
- package/src/entities/plugin/lib/named.ts +21 -0
- package/src/entities/plugin/model/attachment.ts +18 -0
- package/src/entities/plugin/model/http.ts +147 -0
- package/src/entities/plugin/model/page.ts +110 -0
- package/src/entities/plugin/model/plugin.ts +96 -0
- package/src/entities/plugin/model/socket.ts +108 -0
- package/src/entities/plugin/model/stream.ts +43 -0
- package/src/features/connect/index.ts +23 -0
- package/src/features/connect/lib/calls.ts +58 -0
- package/src/features/connect/lib/client.ts +203 -0
- package/src/features/connect/lib/create-connect.ts +164 -0
- package/src/features/connect/lib/faults.ts +132 -0
- package/src/features/connect/lib/protocol.ts +321 -0
- package/src/features/connect/lib/record.ts +48 -0
- package/src/features/connect/lib/recorder.ts +306 -0
- package/src/features/connect/lib/rules.ts +385 -0
- package/src/features/connect/lib/serve.ts +114 -0
- package/src/features/connect/lib/status-of.ts +20 -0
- package/src/features/connect/lib/stubs.ts +282 -0
- package/src/features/connect/lib/universal.ts +100 -0
- package/src/features/connect/model/types.ts +305 -0
- package/src/features/rest/index.ts +23 -0
- package/src/features/rest/lib/calls.ts +31 -0
- package/src/features/rest/lib/create-rest.ts +169 -0
- package/src/features/rest/lib/path.ts +70 -0
- package/src/features/rest/lib/reply.ts +74 -0
- package/src/features/rest/model/types.ts +113 -0
- package/src/features/sse/index.ts +10 -0
- package/src/features/sse/lib/create-sse.ts +128 -0
- package/src/features/sse/lib/encode.ts +28 -0
- package/src/features/sse/model/types.ts +66 -0
- package/src/features/webrtc/index.ts +6 -0
- package/src/features/webrtc/lib/create-webrtc.ts +149 -0
- package/src/features/webrtc/lib/rtc-page-module.ts +189 -0
- package/src/features/webrtc/lib/to-frame.ts +63 -0
- package/src/features/webrtc/model/types.ts +80 -0
- package/src/features/websocket/index.ts +15 -0
- package/src/features/websocket/lib/create-websocket.ts +41 -0
- package/src/features/websocket/lib/mock.ts +114 -0
- package/src/features/websocket/lib/proxy.ts +141 -0
- package/src/features/websocket/lib/wire.ts +78 -0
- package/src/features/websocket/model/types.ts +130 -0
- package/src/index.ts +111 -0
- package/src/playwright.ts +8 -0
- package/src/rest.ts +2 -0
- package/src/shared/api/http-server/index.ts +2 -0
- package/src/shared/api/http-server/listen.ts +71 -0
- package/src/shared/api/playwright/index.ts +17 -0
- package/src/shared/api/playwright/ports.ts +145 -0
- package/src/shared/api/stream-server/index.ts +7 -0
- package/src/shared/api/stream-server/stream-server.ts +246 -0
- package/src/shared/lib/async/arrivals.ts +91 -0
- package/src/shared/lib/async/async-queue.ts +101 -0
- package/src/shared/lib/async/deferred.ts +38 -0
- package/src/shared/lib/async/index.ts +11 -0
- package/src/shared/lib/async/run-all.ts +19 -0
- package/src/shared/lib/bytes/bytes.ts +53 -0
- package/src/shared/lib/bytes/index.ts +9 -0
- package/src/shared/lib/clock/clock.ts +114 -0
- package/src/shared/lib/clock/index.ts +2 -0
- package/src/shared/lib/cookies/index.ts +2 -0
- package/src/shared/lib/cookies/set-cookie.ts +105 -0
- package/src/shared/lib/envelope/envelope.ts +133 -0
- package/src/shared/lib/envelope/index.ts +9 -0
- package/src/shared/lib/errors/index.ts +5 -0
- package/src/shared/lib/errors/wirestage-error.ts +50 -0
- package/src/shared/lib/id/id.ts +29 -0
- package/src/shared/lib/id/index.ts +1 -0
- package/src/shared/lib/logger/index.ts +12 -0
- package/src/shared/lib/logger/logger.ts +126 -0
- package/src/shared/lib/match/index.ts +6 -0
- package/src/shared/lib/match/url-matcher.ts +107 -0
- package/src/sse.ts +2 -0
- package/src/webrtc.ts +2 -0
- package/src/websocket.ts +2 -0
- package/src/widgets/stage/index.ts +9 -0
- package/src/widgets/stage/lib/attached-context.ts +10 -0
- package/src/widgets/stage/lib/create-stage.ts +305 -0
- package/src/widgets/stage/lib/http-router.ts +620 -0
- package/src/widgets/stage/lib/page-host.ts +375 -0
- package/src/widgets/stage/lib/page-runtime.ts +314 -0
- package/src/widgets/stage/lib/reads.ts +128 -0
- package/src/widgets/stage/lib/response-stream.ts +66 -0
- package/src/widgets/stage/lib/socket-router.ts +271 -0
- package/src/widgets/stage/model/stage.ts +108 -0
package/package.json
CHANGED
|
@@ -1,6 +1,141 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@heojeongbo/wirestage",
|
|
3
|
+
"version": "0.1.0",
|
|
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
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "heojeongbo <heojungbo@gmail.com>",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/heojeongbo/wirestage.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/heojeongbo/wirestage#readme",
|
|
13
|
+
"bugs": "https://github.com/heojeongbo/wirestage/issues",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"playwright",
|
|
16
|
+
"testing",
|
|
17
|
+
"mock",
|
|
18
|
+
"grpc-web",
|
|
19
|
+
"connectrpc",
|
|
20
|
+
"grpc",
|
|
21
|
+
"websocket",
|
|
22
|
+
"webrtc",
|
|
23
|
+
"datachannel",
|
|
24
|
+
"sse",
|
|
25
|
+
"e2e"
|
|
26
|
+
],
|
|
27
|
+
"packageManager": "pnpm@11.16.0",
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22.12"
|
|
30
|
+
},
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"src",
|
|
35
|
+
"!src/**/*.test.ts",
|
|
36
|
+
"!src/**/__fixtures__",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"LICENSES.md"
|
|
40
|
+
],
|
|
41
|
+
"exports": {
|
|
42
|
+
".": {
|
|
43
|
+
"types": "./dist/index.d.ts",
|
|
44
|
+
"default": "./dist/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./playwright": {
|
|
47
|
+
"types": "./dist/playwright.d.ts",
|
|
48
|
+
"default": "./dist/playwright.js"
|
|
49
|
+
},
|
|
50
|
+
"./connect": {
|
|
51
|
+
"types": "./dist/connect.d.ts",
|
|
52
|
+
"default": "./dist/connect.js"
|
|
53
|
+
},
|
|
54
|
+
"./rest": {
|
|
55
|
+
"types": "./dist/rest.d.ts",
|
|
56
|
+
"default": "./dist/rest.js"
|
|
57
|
+
},
|
|
58
|
+
"./sse": {
|
|
59
|
+
"types": "./dist/sse.d.ts",
|
|
60
|
+
"default": "./dist/sse.js"
|
|
61
|
+
},
|
|
62
|
+
"./websocket": {
|
|
63
|
+
"types": "./dist/websocket.d.ts",
|
|
64
|
+
"default": "./dist/websocket.js"
|
|
65
|
+
},
|
|
66
|
+
"./webrtc": {
|
|
67
|
+
"types": "./dist/webrtc.d.ts",
|
|
68
|
+
"default": "./dist/webrtc.js"
|
|
69
|
+
},
|
|
70
|
+
"./package.json": "./package.json"
|
|
71
|
+
},
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"scripts": {
|
|
76
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
77
|
+
"build": "pnpm clean && tsc -p tsconfig.build.json",
|
|
78
|
+
"type:check": "tsc --noEmit",
|
|
79
|
+
"lint": "biome check --error-on-warnings .",
|
|
80
|
+
"format": "biome check --write .",
|
|
81
|
+
"fsd:check": "tsx scripts/check-boundaries.ts",
|
|
82
|
+
"test": "vitest run --project unit",
|
|
83
|
+
"test:coverage": "vitest run --project unit --coverage",
|
|
84
|
+
"test:browser": "vitest run --project browser",
|
|
85
|
+
"e2e": "pnpm build && tsc --noEmit -p e2e/tsconfig.json && playwright test",
|
|
86
|
+
"bench": "vitest bench --run --config vitest.bench.config.ts",
|
|
87
|
+
"perf": "tsx scripts/perf.ts",
|
|
88
|
+
"perf:check": "tsx scripts/perf.ts --check",
|
|
89
|
+
"docs:check": "node scripts/check-docs.mjs",
|
|
90
|
+
"package:check": "node scripts/check-package.mjs",
|
|
91
|
+
"gen:proto": "buf generate",
|
|
92
|
+
"check": "pnpm lint && pnpm fsd:check && pnpm type:check && pnpm test:coverage && pnpm build && pnpm docs:check && pnpm package:check",
|
|
93
|
+
"check:browser": "pnpm test:browser && pnpm e2e && pnpm perf:check",
|
|
94
|
+
"prepare": "husky || true",
|
|
95
|
+
"prepack": "pnpm build",
|
|
96
|
+
"prepublishOnly": "pnpm check && pnpm check:browser"
|
|
97
|
+
},
|
|
98
|
+
"dependencies": {
|
|
99
|
+
"@heojeongbo/log-palette": "^0.2.2"
|
|
100
|
+
},
|
|
101
|
+
"peerDependencies": {
|
|
102
|
+
"@bufbuild/protobuf": "^2.10.0",
|
|
103
|
+
"@connectrpc/connect": "^2.1.0",
|
|
104
|
+
"@connectrpc/connect-node": "^2.1.0",
|
|
105
|
+
"@playwright/test": ">=1.50.0"
|
|
106
|
+
},
|
|
107
|
+
"peerDependenciesMeta": {
|
|
108
|
+
"@bufbuild/protobuf": {
|
|
109
|
+
"optional": true
|
|
110
|
+
},
|
|
111
|
+
"@connectrpc/connect": {
|
|
112
|
+
"optional": true
|
|
113
|
+
},
|
|
114
|
+
"@connectrpc/connect-node": {
|
|
115
|
+
"optional": true
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"devDependencies": {
|
|
119
|
+
"@biomejs/biome": "2.5.15",
|
|
120
|
+
"@bufbuild/buf": "1.73.0",
|
|
121
|
+
"@bufbuild/protobuf": "2.12.0",
|
|
122
|
+
"@bufbuild/protoc-gen-es": "2.12.0",
|
|
123
|
+
"@commitlint/cli": "20.1.0",
|
|
124
|
+
"@commitlint/config-conventional": "20.2.0",
|
|
125
|
+
"@connectrpc/connect": "2.1.1",
|
|
126
|
+
"@connectrpc/connect-node": "2.1.1",
|
|
127
|
+
"@connectrpc/connect-web": "2.1.1",
|
|
128
|
+
"@playwright/test": "1.60.0",
|
|
129
|
+
"@types/node": "24.3.0",
|
|
130
|
+
"@vitest/coverage-v8": "4.1.11",
|
|
131
|
+
"esbuild": "0.25.10",
|
|
132
|
+
"husky": "9.1.7",
|
|
133
|
+
"lint-staged": "16.2.7",
|
|
134
|
+
"tsx": "4.20.4",
|
|
135
|
+
"typescript": "5.9.3",
|
|
136
|
+
"vitest": "4.1.11"
|
|
137
|
+
},
|
|
138
|
+
"lint-staged": {
|
|
139
|
+
"*.{ts,mts,js,mjs,json,jsonc}": "biome check --write --no-errors-on-unmatched"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type { TestType } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
import type { AnyWirePlugin } from "../../../entities/plugin/index.js";
|
|
4
|
+
import type { ContextPort } from "../../../shared/api/playwright/index.js";
|
|
5
|
+
import {
|
|
6
|
+
createScopedLogger,
|
|
7
|
+
type LogThreshold,
|
|
8
|
+
parseLogThreshold,
|
|
9
|
+
setLogThreshold,
|
|
10
|
+
} from "../../../shared/lib/logger/index.js";
|
|
11
|
+
import {
|
|
12
|
+
createStage,
|
|
13
|
+
type Stage,
|
|
14
|
+
type StageOptions,
|
|
15
|
+
} from "../../../widgets/stage/index.js";
|
|
16
|
+
|
|
17
|
+
/** When the timeline is attached to the test report. */
|
|
18
|
+
export type ReportMode = "on-failure" | "always" | "never";
|
|
19
|
+
|
|
20
|
+
export interface StageFixtureOptions<Plugins extends readonly AnyWirePlugin[]>
|
|
21
|
+
extends Omit<StageOptions<Plugins>, "baseURL" | "clock"> {
|
|
22
|
+
/**
|
|
23
|
+
* Default `on-failure`. `WIRESTAGE_REPORT` overrides it. An empty timeline
|
|
24
|
+
* is never attached.
|
|
25
|
+
*/
|
|
26
|
+
readonly report?: ReportMode;
|
|
27
|
+
/**
|
|
28
|
+
* Frames a report holds, counting back from the newest. Default 1,000: a
|
|
29
|
+
* report is read from its end, and one that grows with the test would
|
|
30
|
+
* attach tens of megabytes to a long run.
|
|
31
|
+
*/
|
|
32
|
+
readonly reportLimit?: number;
|
|
33
|
+
/** Default `warn`. `WIRESTAGE_LOG` overrides it. */
|
|
34
|
+
readonly log?: LogThreshold;
|
|
35
|
+
/**
|
|
36
|
+
* Attach the test's `context` before the body runs. Default true. Turn it
|
|
37
|
+
* off when tests open their own contexts (`browser.newContext()`, two users
|
|
38
|
+
* at once): the fixture then never asks Playwright for `context`, so no
|
|
39
|
+
* unused one is created, and the test attaches what it opens.
|
|
40
|
+
*/
|
|
41
|
+
readonly attach?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface StageFixtureArgs {
|
|
45
|
+
/** Absent when the fixture does not attach (`attach: false`). */
|
|
46
|
+
readonly context?: ContextPort;
|
|
47
|
+
readonly baseURL: string | undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The part of Playwright's TestInfo the fixture uses. */
|
|
51
|
+
export interface StageTestInfo {
|
|
52
|
+
readonly status?: string;
|
|
53
|
+
readonly expectedStatus: string;
|
|
54
|
+
attach(
|
|
55
|
+
name: string,
|
|
56
|
+
options: { readonly body: string; readonly contentType: string },
|
|
57
|
+
): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type Environment = Readonly<Record<string, string | undefined>>;
|
|
61
|
+
|
|
62
|
+
const REPORT_MODES: readonly ReportMode[] = ["on-failure", "always", "never"];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The environment's say, read once when the fixture is made. A value it
|
|
66
|
+
* cannot use is ignored with one warning: a typo in CI config must neither
|
|
67
|
+
* turn reports off silently nor fail every test, and saying so once is
|
|
68
|
+
* enough.
|
|
69
|
+
*/
|
|
70
|
+
function readEnvironment(env: Environment): {
|
|
71
|
+
readonly report: ReportMode | undefined;
|
|
72
|
+
readonly log: LogThreshold | undefined;
|
|
73
|
+
} {
|
|
74
|
+
const warn = (name: string, value: string, allowed: readonly string[]) =>
|
|
75
|
+
createScopedLogger("Fixture").warn(`ignoring an unknown ${name}`, {
|
|
76
|
+
value,
|
|
77
|
+
allowed,
|
|
78
|
+
});
|
|
79
|
+
const wantedReport = env["WIRESTAGE_REPORT"]?.trim().toLowerCase();
|
|
80
|
+
const report = REPORT_MODES.find((mode) => mode === wantedReport);
|
|
81
|
+
if (wantedReport !== undefined && report === undefined)
|
|
82
|
+
warn("WIRESTAGE_REPORT", wantedReport, REPORT_MODES);
|
|
83
|
+
const wantedLog = env["WIRESTAGE_LOG"];
|
|
84
|
+
const log = parseLogThreshold(wantedLog);
|
|
85
|
+
if (wantedLog !== undefined && log === undefined)
|
|
86
|
+
warn("WIRESTAGE_LOG", wantedLog, [
|
|
87
|
+
"debug",
|
|
88
|
+
"log",
|
|
89
|
+
"info",
|
|
90
|
+
"warn",
|
|
91
|
+
"error",
|
|
92
|
+
"silent",
|
|
93
|
+
]);
|
|
94
|
+
return { report, log };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The `stage` fixture as a plain function, so it can be tested without the
|
|
99
|
+
* Playwright runner: one stage per test, attached to the test's context
|
|
100
|
+
* before the test body runs, reported on failure, disposed afterwards.
|
|
101
|
+
*/
|
|
102
|
+
export function createStageFixture<
|
|
103
|
+
const Plugins extends readonly AnyWirePlugin[],
|
|
104
|
+
>(
|
|
105
|
+
options: StageFixtureOptions<Plugins>,
|
|
106
|
+
env: Environment = process.env,
|
|
107
|
+
): (
|
|
108
|
+
args: StageFixtureArgs,
|
|
109
|
+
use: (stage: Stage<Plugins>) => Promise<void>,
|
|
110
|
+
testInfo: StageTestInfo,
|
|
111
|
+
) => Promise<void> {
|
|
112
|
+
const { report, reportLimit, log, attach = true, ...stageOptions } = options;
|
|
113
|
+
const fromEnv = readEnvironment(env);
|
|
114
|
+
const threshold = fromEnv.log ?? log;
|
|
115
|
+
if (threshold !== undefined) setLogThreshold(threshold);
|
|
116
|
+
const mode = fromEnv.report ?? report ?? "on-failure";
|
|
117
|
+
const fixtureLog = createScopedLogger("Fixture");
|
|
118
|
+
|
|
119
|
+
/** Attach the timeline to the test's report, when there is one to read. */
|
|
120
|
+
const attachReport = async (
|
|
121
|
+
stage: Stage<Plugins>,
|
|
122
|
+
testInfo: StageTestInfo,
|
|
123
|
+
): Promise<void> => {
|
|
124
|
+
const failed = testInfo.status !== testInfo.expectedStatus;
|
|
125
|
+
if (mode === "never" || (mode === "on-failure" && !failed)) return;
|
|
126
|
+
// What the pages still hold is often the frame the failure is about.
|
|
127
|
+
await stage.sync();
|
|
128
|
+
// Nothing on the timeline is nothing to read: no empty attachment.
|
|
129
|
+
if (stage.timeline.size === 0 && stage.timeline.evicted === 0) return;
|
|
130
|
+
const { snapshot, text } = stage.report(
|
|
131
|
+
undefined,
|
|
132
|
+
reportLimit === undefined ? {} : { limit: reportLimit },
|
|
133
|
+
);
|
|
134
|
+
await testInfo.attach("wirestage-timeline.txt", {
|
|
135
|
+
body: text,
|
|
136
|
+
contentType: "text/plain",
|
|
137
|
+
});
|
|
138
|
+
await testInfo.attach("wirestage-timeline.json", {
|
|
139
|
+
body: JSON.stringify(snapshot, null, 2),
|
|
140
|
+
contentType: "application/json",
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const run = async (
|
|
145
|
+
context: ContextPort | undefined,
|
|
146
|
+
baseURL: string | undefined,
|
|
147
|
+
use: (stage: Stage<Plugins>) => Promise<void>,
|
|
148
|
+
testInfo: StageTestInfo,
|
|
149
|
+
): Promise<void> => {
|
|
150
|
+
const stage = createStage({
|
|
151
|
+
...stageOptions,
|
|
152
|
+
...(baseURL === undefined ? {} : { baseURL }),
|
|
153
|
+
});
|
|
154
|
+
try {
|
|
155
|
+
if (context !== undefined) await stage.attach(context);
|
|
156
|
+
await use(stage);
|
|
157
|
+
} finally {
|
|
158
|
+
try {
|
|
159
|
+
await attachReport(stage, testInfo);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
// The report is a courtesy; failing to write one must not hide
|
|
162
|
+
// the test's own result, nor keep the stage from being disposed.
|
|
163
|
+
fixtureLog.warn("could not attach the timeline", {}, error);
|
|
164
|
+
} finally {
|
|
165
|
+
await stage.dispose();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
// Playwright reads a fixture's dependencies off its SOURCE, so each mode
|
|
170
|
+
// is its own literal: naming `context` is what makes Playwright create one.
|
|
171
|
+
return attach
|
|
172
|
+
? async ({ context, baseURL }, use, testInfo) =>
|
|
173
|
+
run(context, baseURL, use, testInfo)
|
|
174
|
+
: async ({ baseURL }, use, testInfo) =>
|
|
175
|
+
run(undefined, baseURL, use, testInfo);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Extend a Playwright `test` with a `stage` fixture:
|
|
180
|
+
*
|
|
181
|
+
* export const test = withStage(base, { plugins: [webrtc(), connect()] });
|
|
182
|
+
* test("...", async ({ page, stage }) => { ... });
|
|
183
|
+
*/
|
|
184
|
+
export function withStage<
|
|
185
|
+
Args extends object,
|
|
186
|
+
Workers extends object,
|
|
187
|
+
const Plugins extends readonly AnyWirePlugin[],
|
|
188
|
+
>(
|
|
189
|
+
test: TestType<Args, Workers>,
|
|
190
|
+
options: StageFixtureOptions<Plugins>,
|
|
191
|
+
): TestType<Args & { stage: Stage<Plugins> }, Workers> {
|
|
192
|
+
// Playwright reads a fixture's dependencies off the SOURCE of its first
|
|
193
|
+
// parameter, so the fixture must be passed as written — with its
|
|
194
|
+
// `({ context, baseURL }, use, testInfo)` destructuring — not wrapped. The
|
|
195
|
+
// cast is only for the generic `extend` signature, which TypeScript cannot
|
|
196
|
+
// resolve against an arbitrary `Args`.
|
|
197
|
+
const extend = test.extend.bind(test) as unknown as (fixtures: {
|
|
198
|
+
readonly stage: ReturnType<typeof createStageFixture<Plugins>>;
|
|
199
|
+
}) => TestType<Args & { stage: Stage<Plugins> }, Workers>;
|
|
200
|
+
return extend({ stage: createStageFixture(options) });
|
|
201
|
+
}
|
package/src/connect.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The frame types the plugin contract is written in terms of.
|
|
3
|
+
*
|
|
4
|
+
* FSD's cross-import notation: `entities/plugin` may import this file and
|
|
5
|
+
* nothing else from `entities/frame`. It keeps the dependency between the two
|
|
6
|
+
* entities explicit and one-way — the frame model knows nothing of plugins.
|
|
7
|
+
*/
|
|
8
|
+
export type { Frame, FrameFilter, Timeline } from "../model/frame.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { compileFilter } from "./lib/filter.js";
|
|
2
|
+
export { createPayload } from "./lib/payload.js";
|
|
3
|
+
export type { TimelineOptions } from "./lib/timeline.js";
|
|
4
|
+
export { createTimeline } from "./lib/timeline.js";
|
|
5
|
+
export type {
|
|
6
|
+
Direction,
|
|
7
|
+
Frame,
|
|
8
|
+
FrameFilter,
|
|
9
|
+
FrameInit,
|
|
10
|
+
FrameKind,
|
|
11
|
+
FrameSource,
|
|
12
|
+
Payload,
|
|
13
|
+
PayloadInput,
|
|
14
|
+
SnapshotFrame,
|
|
15
|
+
SnapshotOptions,
|
|
16
|
+
Timeline,
|
|
17
|
+
TimelineCursor,
|
|
18
|
+
TimelineSnapshot,
|
|
19
|
+
} from "./model/frame.js";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Frame, FrameFilter } from "../model/frame.js";
|
|
2
|
+
|
|
3
|
+
const ALWAYS = () => true;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Compile a filter into one predicate. Queries run over every frame of a long
|
|
7
|
+
* test, often in a polling loop, so the per-frame work is a handful of
|
|
8
|
+
* comparisons and the `where` callback runs only after the cheap fields pass.
|
|
9
|
+
*/
|
|
10
|
+
export function compileFilter(
|
|
11
|
+
filter: FrameFilter | undefined,
|
|
12
|
+
): (frame: Frame) => boolean {
|
|
13
|
+
if (filter === undefined) return ALWAYS;
|
|
14
|
+
const checks: ((frame: Frame) => boolean)[] = [];
|
|
15
|
+
const { protocol, kind, endpoint, where } = filter;
|
|
16
|
+
if (protocol !== undefined) {
|
|
17
|
+
if (typeof protocol === "string")
|
|
18
|
+
checks.push((f) => f.protocol === protocol);
|
|
19
|
+
else {
|
|
20
|
+
const set = new Set(protocol);
|
|
21
|
+
checks.push((f) => set.has(f.protocol));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (kind !== undefined) {
|
|
25
|
+
if (typeof kind === "string") checks.push((f) => f.kind === kind);
|
|
26
|
+
else {
|
|
27
|
+
const set = new Set(kind);
|
|
28
|
+
checks.push((f) => set.has(f.kind));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const key of [
|
|
32
|
+
"direction",
|
|
33
|
+
"source",
|
|
34
|
+
"page",
|
|
35
|
+
"context",
|
|
36
|
+
"correlation",
|
|
37
|
+
] as const) {
|
|
38
|
+
const expected = filter[key];
|
|
39
|
+
if (expected !== undefined) checks.push((f) => f[key] === expected);
|
|
40
|
+
}
|
|
41
|
+
if (endpoint !== undefined) {
|
|
42
|
+
if (typeof endpoint === "string")
|
|
43
|
+
checks.push((f) => f.endpoint === endpoint);
|
|
44
|
+
else
|
|
45
|
+
checks.push((f) => {
|
|
46
|
+
endpoint.lastIndex = 0;
|
|
47
|
+
return endpoint.test(f.endpoint);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const after = filter.after;
|
|
51
|
+
if (after !== undefined) checks.push((f) => f.seq > after);
|
|
52
|
+
if (where !== undefined) checks.push(where);
|
|
53
|
+
if (checks.length === 0) return ALWAYS;
|
|
54
|
+
return (frame) => {
|
|
55
|
+
for (const check of checks) if (!check(frame)) return false;
|
|
56
|
+
return true;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { toBytes, utf8 } from "../../../shared/lib/bytes/index.js";
|
|
2
|
+
import type { Payload, PayloadInput } from "../model/frame.js";
|
|
3
|
+
|
|
4
|
+
const EMPTY = new Uint8Array(0);
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A payload that converts lazily and remembers every conversion. Frames are
|
|
8
|
+
* written far more often than read, so nothing is encoded or decoded until a
|
|
9
|
+
* test asks, and asking twice costs once.
|
|
10
|
+
*/
|
|
11
|
+
export function createPayload(input: PayloadInput | undefined): Payload {
|
|
12
|
+
let bytes: Uint8Array | undefined =
|
|
13
|
+
input instanceof Uint8Array ? input : undefined;
|
|
14
|
+
let text: string | undefined = typeof input === "string" ? input : undefined;
|
|
15
|
+
let decoded: WeakMap<(bytes: Uint8Array) => unknown, unknown> | undefined;
|
|
16
|
+
|
|
17
|
+
const getBytes = (): Uint8Array => {
|
|
18
|
+
if (bytes !== undefined) return bytes;
|
|
19
|
+
if (typeof input === "function") bytes = input();
|
|
20
|
+
else if (text !== undefined) bytes = toBytes(text);
|
|
21
|
+
else bytes = EMPTY;
|
|
22
|
+
return bytes;
|
|
23
|
+
};
|
|
24
|
+
const getText = (): string => {
|
|
25
|
+
text ??= utf8(getBytes());
|
|
26
|
+
return text;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
empty: input === undefined,
|
|
31
|
+
bytes: getBytes,
|
|
32
|
+
text: getText,
|
|
33
|
+
json: <T>() => JSON.parse(getText()) as T,
|
|
34
|
+
decode<T>(decoder: (bytes: Uint8Array) => T): T {
|
|
35
|
+
decoded ??= new WeakMap();
|
|
36
|
+
if (decoded.has(decoder)) return decoded.get(decoder) as T;
|
|
37
|
+
const value = decoder(getBytes());
|
|
38
|
+
decoded.set(decoder, value);
|
|
39
|
+
return value;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { toBase64 } from "../../../shared/lib/bytes/index.js";
|
|
2
|
+
import type {
|
|
3
|
+
Frame,
|
|
4
|
+
SnapshotFrame,
|
|
5
|
+
SnapshotOptions,
|
|
6
|
+
TimelineSnapshot,
|
|
7
|
+
} from "../model/frame.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A JSON-safe copy of `frames`, with payloads cut at `maxBytes` and, given a
|
|
11
|
+
* `limit`, only the newest frames kept: a report is read from its end.
|
|
12
|
+
*/
|
|
13
|
+
export function snapshotFrames(
|
|
14
|
+
frames: readonly Frame[],
|
|
15
|
+
evicted: number,
|
|
16
|
+
options: SnapshotOptions = {},
|
|
17
|
+
): TimelineSnapshot {
|
|
18
|
+
const maxBytes = options.maxBytes ?? 4096;
|
|
19
|
+
const kept =
|
|
20
|
+
options.limit === undefined || frames.length <= options.limit
|
|
21
|
+
? frames
|
|
22
|
+
: frames.slice(frames.length - options.limit);
|
|
23
|
+
return {
|
|
24
|
+
evicted,
|
|
25
|
+
omitted: frames.length - kept.length,
|
|
26
|
+
frames: kept.map((frame): SnapshotFrame => {
|
|
27
|
+
const base: SnapshotFrame = {
|
|
28
|
+
seq: frame.seq,
|
|
29
|
+
at: frame.at,
|
|
30
|
+
protocol: frame.protocol,
|
|
31
|
+
kind: frame.kind,
|
|
32
|
+
direction: frame.direction,
|
|
33
|
+
endpoint: frame.endpoint,
|
|
34
|
+
source: frame.source,
|
|
35
|
+
...(frame.page === undefined ? {} : { page: frame.page }),
|
|
36
|
+
...(frame.context === undefined ? {} : { context: frame.context }),
|
|
37
|
+
...(frame.correlation === undefined
|
|
38
|
+
? {}
|
|
39
|
+
: { correlation: frame.correlation }),
|
|
40
|
+
...(Object.keys(frame.meta).length === 0
|
|
41
|
+
? {}
|
|
42
|
+
: { meta: jsonSafe(frame.meta) }),
|
|
43
|
+
};
|
|
44
|
+
if (frame.payload.empty) return base;
|
|
45
|
+
const bytes = frame.payload.bytes();
|
|
46
|
+
return {
|
|
47
|
+
...base,
|
|
48
|
+
size: bytes.byteLength,
|
|
49
|
+
data: toBase64(bytes.subarray(0, maxBytes)),
|
|
50
|
+
...(bytes.byteLength > maxBytes ? { truncated: true } : {}),
|
|
51
|
+
};
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* One line per frame: `#12 +3.2ms connect out request pkg.Svc/Method 42B`.
|
|
58
|
+
* Times are relative to the first frame listed, which is what a reader of a
|
|
59
|
+
* failure report compares.
|
|
60
|
+
*/
|
|
61
|
+
export function formatFrames(
|
|
62
|
+
frames: readonly Frame[],
|
|
63
|
+
options: { readonly limit?: number } = {},
|
|
64
|
+
): string {
|
|
65
|
+
const limit = options.limit ?? 200;
|
|
66
|
+
// Not `slice(-limit)`: a limit of 0 would be `slice(-0)`, every frame.
|
|
67
|
+
const shown =
|
|
68
|
+
frames.length > limit ? frames.slice(frames.length - limit) : frames;
|
|
69
|
+
const origin = shown[0]?.at ?? 0;
|
|
70
|
+
const lines = shown.map((frame) => {
|
|
71
|
+
const size = frame.payload.empty
|
|
72
|
+
? ""
|
|
73
|
+
: ` ${frame.payload.bytes().byteLength}B`;
|
|
74
|
+
const page = frame.page === undefined ? "" : ` ${frame.page}`;
|
|
75
|
+
return `#${frame.seq} +${(frame.at - origin).toFixed(1)}ms ${frame.protocol} ${frame.direction} ${frame.kind} ${frame.endpoint}${page}${size}`;
|
|
76
|
+
});
|
|
77
|
+
if (frames.length > limit)
|
|
78
|
+
lines.unshift(`… ${frames.length - limit} earlier frames not shown`);
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Make `meta` survive `JSON.stringify`: a bigint (protobuf int64) or a cycle
|
|
84
|
+
* would otherwise throw while writing the report — at the exact moment a test
|
|
85
|
+
* has already failed and the report is the only evidence.
|
|
86
|
+
*/
|
|
87
|
+
function jsonSafe(
|
|
88
|
+
meta: Readonly<Record<string, unknown>>,
|
|
89
|
+
): Record<string, unknown> {
|
|
90
|
+
// The objects on the path from the root to the value being written. Only
|
|
91
|
+
// those make a cycle: an object met again elsewhere is merely shared.
|
|
92
|
+
const ancestors: object[] = [];
|
|
93
|
+
return JSON.parse(
|
|
94
|
+
JSON.stringify(meta, function (this: unknown, _key, value: unknown) {
|
|
95
|
+
if (typeof value === "bigint") return value.toString();
|
|
96
|
+
if (value instanceof Uint8Array) return toBase64(value);
|
|
97
|
+
if (typeof value !== "object" || value === null) return value;
|
|
98
|
+
// `this` holds `value`: whatever was above it is finished.
|
|
99
|
+
while (ancestors.length > 0 && ancestors.at(-1) !== this) ancestors.pop();
|
|
100
|
+
if (ancestors.includes(value)) return "[circular]";
|
|
101
|
+
ancestors.push(value);
|
|
102
|
+
return value;
|
|
103
|
+
}),
|
|
104
|
+
) as Record<string, unknown>;
|
|
105
|
+
}
|