@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
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DescMessage,
|
|
3
|
+
DescMethod,
|
|
4
|
+
DescMethodServerStreaming,
|
|
5
|
+
DescMethodUnary,
|
|
6
|
+
MessageInitShape,
|
|
7
|
+
MessageShape,
|
|
8
|
+
} from "@bufbuild/protobuf";
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
AbortErrorCode,
|
|
12
|
+
HttpOutcome,
|
|
13
|
+
PluginContext,
|
|
14
|
+
} from "../../../entities/plugin/index.js";
|
|
15
|
+
import {
|
|
16
|
+
createArrivals,
|
|
17
|
+
createDeferred,
|
|
18
|
+
} from "../../../shared/lib/async/index.js";
|
|
19
|
+
import type {
|
|
20
|
+
HeldCall,
|
|
21
|
+
HoldOptions,
|
|
22
|
+
HoldStub,
|
|
23
|
+
StubHandle,
|
|
24
|
+
StubOptions,
|
|
25
|
+
} from "../model/types.js";
|
|
26
|
+
import { endpointOf, type Recorder } from "./recorder.js";
|
|
27
|
+
import type { AnyImpl, RpcRules } from "./rules.js";
|
|
28
|
+
import { failingImpl, handleOf } from "./stubs.js";
|
|
29
|
+
|
|
30
|
+
/** Fail every call to a method at the network level. */
|
|
31
|
+
export async function stubAbort<I extends DescMessage>(
|
|
32
|
+
rules: RpcRules,
|
|
33
|
+
recorder: Recorder,
|
|
34
|
+
method: DescMethod & { readonly input: I },
|
|
35
|
+
options: StubOptions<I> & { readonly error?: AbortErrorCode },
|
|
36
|
+
): Promise<StubHandle> {
|
|
37
|
+
const error = options.error ?? "failed";
|
|
38
|
+
return handleOf(
|
|
39
|
+
await rules.add({
|
|
40
|
+
method,
|
|
41
|
+
label: `abort ${endpointOf(method)}`,
|
|
42
|
+
options,
|
|
43
|
+
respond(view) {
|
|
44
|
+
recorder.fault(rules.callOf(view), method, "abort", { error });
|
|
45
|
+
return { type: "abort", error };
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Hold calls at the network boundary until the test decides each one. The
|
|
53
|
+
* returned `abandon` lets go of whatever is still held, for the stage's
|
|
54
|
+
* disposal: a route left undecided would keep its request open for good.
|
|
55
|
+
*/
|
|
56
|
+
export async function stubHold<I extends DescMessage, O extends DescMessage>(
|
|
57
|
+
context: PluginContext,
|
|
58
|
+
rules: RpcRules,
|
|
59
|
+
recorder: Recorder,
|
|
60
|
+
method: DescMethodUnary<I, O> | DescMethodServerStreaming<I, O>,
|
|
61
|
+
options: HoldOptions<I>,
|
|
62
|
+
pending: Set<() => void>,
|
|
63
|
+
): Promise<HoldStub<I, O>> {
|
|
64
|
+
const calls = createArrivals<HeldCall<I, O>>({
|
|
65
|
+
clock: context.clock,
|
|
66
|
+
label: `${endpointOf(method)} held call`,
|
|
67
|
+
});
|
|
68
|
+
const rule = await rules.add({
|
|
69
|
+
method,
|
|
70
|
+
label: `hold ${endpointOf(method)}`,
|
|
71
|
+
options,
|
|
72
|
+
observe: true,
|
|
73
|
+
async respond(view, [request]) {
|
|
74
|
+
const decision =
|
|
75
|
+
createDeferred<() => HttpOutcome | Promise<HttpOutcome>>();
|
|
76
|
+
const carried = createDeferred<void>();
|
|
77
|
+
/** The first decision stands; each resolves once it is carried out. */
|
|
78
|
+
const decide = (make: () => HttpOutcome | Promise<HttpOutcome>) => {
|
|
79
|
+
decision.resolve(make);
|
|
80
|
+
return carried.promise;
|
|
81
|
+
};
|
|
82
|
+
const aborted = (error: AbortErrorCode) => () => {
|
|
83
|
+
recorder.fault(rules.callOf(view), method, "abort", { error });
|
|
84
|
+
return { type: "abort", error } as const;
|
|
85
|
+
};
|
|
86
|
+
const answered = (impl: AnyImpl) => () =>
|
|
87
|
+
rules.answer(rules.handler(method, impl), method, view);
|
|
88
|
+
const abandon = () => void decide(aborted("aborted"));
|
|
89
|
+
pending.add(abandon);
|
|
90
|
+
calls.push({
|
|
91
|
+
request: request as MessageShape<I> | undefined,
|
|
92
|
+
view,
|
|
93
|
+
release: () => decide(() => ({ type: "fallback" })),
|
|
94
|
+
reply: (message: MessageInitShape<O>) =>
|
|
95
|
+
decide(
|
|
96
|
+
answered(
|
|
97
|
+
(method.methodKind === "server_streaming"
|
|
98
|
+
? async function* () {
|
|
99
|
+
yield message;
|
|
100
|
+
}
|
|
101
|
+
: async () => message) as AnyImpl,
|
|
102
|
+
),
|
|
103
|
+
),
|
|
104
|
+
fail: (code, message) =>
|
|
105
|
+
decide(answered(failingImpl(method, code, message))),
|
|
106
|
+
abort: (error) => decide(aborted(error ?? "failed")),
|
|
107
|
+
});
|
|
108
|
+
try {
|
|
109
|
+
return await (await decision.promise)();
|
|
110
|
+
} finally {
|
|
111
|
+
pending.delete(abandon);
|
|
112
|
+
carried.resolve();
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
return {
|
|
117
|
+
...handleOf(rule),
|
|
118
|
+
get hits() {
|
|
119
|
+
return rule.hits;
|
|
120
|
+
},
|
|
121
|
+
next: (waitOptions) => calls.next(waitOptions),
|
|
122
|
+
get calls() {
|
|
123
|
+
return calls.items;
|
|
124
|
+
},
|
|
125
|
+
async releaseAll() {
|
|
126
|
+
// Removed first: a call on its way in as this runs is not the
|
|
127
|
+
// rule's any more, and goes straight on instead of being held.
|
|
128
|
+
await rule.remove();
|
|
129
|
+
await Promise.all(calls.items.map((call) => call.release()));
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { gunzipSync } from "node:zlib";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type DescMessage,
|
|
5
|
+
fromBinary,
|
|
6
|
+
fromJsonString,
|
|
7
|
+
type JsonReadOptions,
|
|
8
|
+
type MessageShape,
|
|
9
|
+
} from "@bufbuild/protobuf";
|
|
10
|
+
import { Code } from "@connectrpc/connect";
|
|
11
|
+
import {
|
|
12
|
+
codeFromString,
|
|
13
|
+
codeFromHttpStatus as connectCodeFromHttpStatus,
|
|
14
|
+
} from "@connectrpc/connect/protocol-connect";
|
|
15
|
+
import { codeFromHttpStatus as grpcCodeFromHttpStatus } from "@connectrpc/connect/protocol-grpc";
|
|
16
|
+
|
|
17
|
+
import type {
|
|
18
|
+
HttpRequestView,
|
|
19
|
+
PassthroughResponse,
|
|
20
|
+
} from "../../../entities/plugin/index.js";
|
|
21
|
+
import {
|
|
22
|
+
concatBytes,
|
|
23
|
+
fromBase64,
|
|
24
|
+
utf8,
|
|
25
|
+
} from "../../../shared/lib/bytes/index.js";
|
|
26
|
+
import {
|
|
27
|
+
decodeEnvelopes,
|
|
28
|
+
EnvelopeFlag,
|
|
29
|
+
parseTrailerBlock,
|
|
30
|
+
} from "../../../shared/lib/envelope/index.js";
|
|
31
|
+
import type { RpcProtocol } from "../model/types.js";
|
|
32
|
+
|
|
33
|
+
/** How one request (and so its response) is encoded on the wire. */
|
|
34
|
+
export interface WireFormat {
|
|
35
|
+
readonly protocol: RpcProtocol;
|
|
36
|
+
/** Protobuf binary, or JSON. */
|
|
37
|
+
readonly binary: boolean;
|
|
38
|
+
/** gRPC-web-text: the whole body is base64. */
|
|
39
|
+
readonly base64: boolean;
|
|
40
|
+
/** Length-prefixed envelopes (every protocol's streaming form). */
|
|
41
|
+
readonly enveloped: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Read the format off a request, the way a Connect server negotiates it.
|
|
46
|
+
* Undefined means "not an RPC this plugin understands" — a rule then falls
|
|
47
|
+
* through instead of mangling, say, a REST call that shares the path prefix.
|
|
48
|
+
*/
|
|
49
|
+
export function detectFormat(
|
|
50
|
+
request: Pick<HttpRequestView, "method" | "url" | "headers">,
|
|
51
|
+
): WireFormat | undefined {
|
|
52
|
+
const contentType = (request.headers["content-type"] ?? "")
|
|
53
|
+
.split(";")[0]
|
|
54
|
+
?.trim()
|
|
55
|
+
.toLowerCase();
|
|
56
|
+
if (contentType?.startsWith("application/grpc-web-text"))
|
|
57
|
+
return {
|
|
58
|
+
protocol: "grpc-web",
|
|
59
|
+
binary: !contentType.endsWith("+json"),
|
|
60
|
+
base64: true,
|
|
61
|
+
enveloped: true,
|
|
62
|
+
};
|
|
63
|
+
if (contentType?.startsWith("application/grpc-web"))
|
|
64
|
+
return {
|
|
65
|
+
protocol: "grpc-web",
|
|
66
|
+
binary: !contentType.endsWith("+json"),
|
|
67
|
+
base64: false,
|
|
68
|
+
enveloped: true,
|
|
69
|
+
};
|
|
70
|
+
if (contentType?.startsWith("application/grpc"))
|
|
71
|
+
return {
|
|
72
|
+
protocol: "grpc",
|
|
73
|
+
binary: !contentType.endsWith("+json"),
|
|
74
|
+
base64: false,
|
|
75
|
+
enveloped: true,
|
|
76
|
+
};
|
|
77
|
+
if (contentType?.startsWith("application/connect+"))
|
|
78
|
+
return {
|
|
79
|
+
protocol: "connect",
|
|
80
|
+
binary: contentType === "application/connect+proto",
|
|
81
|
+
base64: false,
|
|
82
|
+
enveloped: true,
|
|
83
|
+
};
|
|
84
|
+
if (contentType === "application/proto" || contentType === "application/json")
|
|
85
|
+
return {
|
|
86
|
+
protocol: "connect",
|
|
87
|
+
binary: contentType === "application/proto",
|
|
88
|
+
base64: false,
|
|
89
|
+
enveloped: false,
|
|
90
|
+
};
|
|
91
|
+
// Connect's GET form for side-effect-free methods carries the message in
|
|
92
|
+
// the query string and sends no content type at all.
|
|
93
|
+
if (
|
|
94
|
+
request.method === "GET" &&
|
|
95
|
+
request.url.searchParams.get("connect") === "v1"
|
|
96
|
+
)
|
|
97
|
+
return {
|
|
98
|
+
protocol: "connect",
|
|
99
|
+
binary: request.url.searchParams.get("encoding") !== "json",
|
|
100
|
+
base64: false,
|
|
101
|
+
enveloped: false,
|
|
102
|
+
};
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface RpcStatus {
|
|
107
|
+
/** 0 is OK; otherwise the gRPC / Connect code number. */
|
|
108
|
+
readonly code: number;
|
|
109
|
+
readonly message: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface DecodedBody {
|
|
113
|
+
/** Message payloads, decompressed when the encoding is gzip. */
|
|
114
|
+
readonly messages: readonly Uint8Array[];
|
|
115
|
+
readonly status: RpcStatus | undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const OK: RpcStatus = { code: 0, message: "" };
|
|
119
|
+
|
|
120
|
+
/** The request's messages, from its body or (Connect GET) its query. */
|
|
121
|
+
export function decodeRequestBody(
|
|
122
|
+
format: WireFormat,
|
|
123
|
+
request: Pick<HttpRequestView, "url" | "headers" | "body">,
|
|
124
|
+
): Uint8Array[] {
|
|
125
|
+
if (!format.enveloped) {
|
|
126
|
+
const query = request.url.searchParams;
|
|
127
|
+
if (query.get("connect") === "v1") {
|
|
128
|
+
const message = query.get("message") ?? "";
|
|
129
|
+
return [
|
|
130
|
+
query.get("base64") === "1"
|
|
131
|
+
? fromBase64(message.replaceAll("-", "+").replaceAll("_", "/"))
|
|
132
|
+
: new TextEncoder().encode(message),
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
return [request.body()];
|
|
136
|
+
}
|
|
137
|
+
const body = format.base64
|
|
138
|
+
? fromBase64Stream(request.body())
|
|
139
|
+
: request.body();
|
|
140
|
+
return dataEnvelopes(
|
|
141
|
+
body,
|
|
142
|
+
request.headers[
|
|
143
|
+
format.protocol === "connect"
|
|
144
|
+
? "connect-content-encoding"
|
|
145
|
+
: "grpc-encoding"
|
|
146
|
+
],
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Messages and status from a response the real backend sent. */
|
|
151
|
+
export function decodeResponseBody(
|
|
152
|
+
format: WireFormat,
|
|
153
|
+
response: PassthroughResponse,
|
|
154
|
+
): DecodedBody {
|
|
155
|
+
const headers = response.headers;
|
|
156
|
+
const raw = response.body ?? new Uint8Array(0);
|
|
157
|
+
if (!format.enveloped) {
|
|
158
|
+
if (response.status !== 200)
|
|
159
|
+
return { messages: [], status: connectError(raw, response.status) };
|
|
160
|
+
// A 200 that is not a message is something on the way — a proxy's
|
|
161
|
+
// sign-in page, say — and a Connect client reports it as an error.
|
|
162
|
+
const contentType = headers["content-type"] ?? "";
|
|
163
|
+
if (!/^application\/(proto|json)\b/i.test(contentType))
|
|
164
|
+
return {
|
|
165
|
+
messages: [],
|
|
166
|
+
status: {
|
|
167
|
+
code: Code.Unknown,
|
|
168
|
+
message: `unexpected content type "${contentType}"`,
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
return { messages: [raw], status: OK };
|
|
172
|
+
}
|
|
173
|
+
const body = format.base64 ? fromBase64Stream(raw) : raw;
|
|
174
|
+
const { envelopes } = decodeEnvelopes(body);
|
|
175
|
+
const encoding =
|
|
176
|
+
headers[
|
|
177
|
+
format.protocol === "connect"
|
|
178
|
+
? "connect-content-encoding"
|
|
179
|
+
: "grpc-encoding"
|
|
180
|
+
];
|
|
181
|
+
const messages: Uint8Array[] = [];
|
|
182
|
+
let status: RpcStatus | undefined;
|
|
183
|
+
for (const envelope of envelopes) {
|
|
184
|
+
if (
|
|
185
|
+
format.protocol === "connect" &&
|
|
186
|
+
envelope.flags & EnvelopeFlag.endStream
|
|
187
|
+
)
|
|
188
|
+
status = endStream(inflate(envelope.flags, envelope.data, encoding));
|
|
189
|
+
else if (envelope.flags & EnvelopeFlag.trailer)
|
|
190
|
+
status = grpcStatus(parseTrailerBlock(envelope.data));
|
|
191
|
+
else messages.push(inflate(envelope.flags, envelope.data, encoding));
|
|
192
|
+
}
|
|
193
|
+
// A trailers-only response carries the status in the headers instead.
|
|
194
|
+
if (status === undefined && headers["grpc-status"] !== undefined)
|
|
195
|
+
status = grpcStatus(headers);
|
|
196
|
+
// No status anywhere and not a 200: a gateway answered, not the server.
|
|
197
|
+
// The client maps the HTTP status to a code, and so does the record.
|
|
198
|
+
if (status === undefined && response.status !== 200)
|
|
199
|
+
status = {
|
|
200
|
+
code:
|
|
201
|
+
format.protocol === "connect"
|
|
202
|
+
? connectCodeFromHttpStatus(response.status)
|
|
203
|
+
: grpcCodeFromHttpStatus(response.status),
|
|
204
|
+
message: `HTTP ${response.status}`,
|
|
205
|
+
};
|
|
206
|
+
return { messages, status };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Parse a message payload with the request's format. */
|
|
210
|
+
export function parseMessage<Desc extends DescMessage>(
|
|
211
|
+
schema: Desc,
|
|
212
|
+
bytes: Uint8Array,
|
|
213
|
+
binary: boolean,
|
|
214
|
+
jsonOptions?: Partial<JsonReadOptions>,
|
|
215
|
+
): MessageShape<Desc> {
|
|
216
|
+
return binary
|
|
217
|
+
? fromBinary(schema, bytes)
|
|
218
|
+
: fromJsonString(schema, utf8(bytes), {
|
|
219
|
+
ignoreUnknownFields: true,
|
|
220
|
+
...jsonOptions,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Connect's `{ "code": "not_found", "message": "..." }` error body. A body
|
|
226
|
+
* that is not one came from something on the way, and the HTTP status is all
|
|
227
|
+
* there is to go by — which is how a Connect client reads it too.
|
|
228
|
+
*/
|
|
229
|
+
export function connectError(body: Uint8Array, httpStatus: number): RpcStatus {
|
|
230
|
+
try {
|
|
231
|
+
const status = errorStatus(JSON.parse(utf8(body)));
|
|
232
|
+
if (status !== undefined) return status;
|
|
233
|
+
} catch {
|
|
234
|
+
// Not JSON at all.
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
code: connectCodeFromHttpStatus(httpStatus),
|
|
238
|
+
message: `HTTP ${httpStatus}`,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** The status in a Connect error object; undefined when it names no code. */
|
|
243
|
+
function errorStatus(value: unknown): RpcStatus | undefined {
|
|
244
|
+
const error = (typeof value === "object" && value !== null ? value : {}) as {
|
|
245
|
+
readonly code?: unknown;
|
|
246
|
+
readonly message?: unknown;
|
|
247
|
+
};
|
|
248
|
+
const code =
|
|
249
|
+
typeof error.code === "string" ? codeFromString(error.code) : undefined;
|
|
250
|
+
if (code === undefined) return undefined;
|
|
251
|
+
return {
|
|
252
|
+
code,
|
|
253
|
+
message: typeof error.message === "string" ? error.message : "",
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function grpcStatus(fields: Readonly<Record<string, string>>): RpcStatus {
|
|
258
|
+
const code = Number(fields["grpc-status"]);
|
|
259
|
+
return {
|
|
260
|
+
code: Number.isInteger(code) ? code : Code.Unknown,
|
|
261
|
+
message: safeDecodeURIComponent(fields["grpc-message"] ?? ""),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Connect's end-of-stream JSON: `{}` for OK, `{ "error": {...} }` otherwise. */
|
|
266
|
+
function endStream(data: Uint8Array): RpcStatus {
|
|
267
|
+
try {
|
|
268
|
+
const parsed = JSON.parse(utf8(data)) as { readonly error?: unknown };
|
|
269
|
+
if (parsed.error === undefined) return OK;
|
|
270
|
+
return (
|
|
271
|
+
errorStatus(parsed.error) ?? {
|
|
272
|
+
code: Code.Unknown,
|
|
273
|
+
message: "end-of-stream error with no code",
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
} catch {
|
|
277
|
+
return { code: Code.Unknown, message: "malformed end-of-stream message" };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* gRPC-web-text: base64, but not one base64 string. A server encodes each
|
|
283
|
+
* chunk it flushes on its own, padding included, so a stream is several
|
|
284
|
+
* encodings end to end, and decoding it as one stops at the first padding.
|
|
285
|
+
*/
|
|
286
|
+
function fromBase64Stream(body: Uint8Array): Uint8Array {
|
|
287
|
+
const parts = utf8(body).match(/[^=]+=*/g) ?? [];
|
|
288
|
+
return concatBytes(parts.map((part) => fromBase64(part)));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function dataEnvelopes(
|
|
292
|
+
body: Uint8Array,
|
|
293
|
+
encoding: string | undefined,
|
|
294
|
+
): Uint8Array[] {
|
|
295
|
+
return decodeEnvelopes(body)
|
|
296
|
+
.envelopes.filter(
|
|
297
|
+
(e) =>
|
|
298
|
+
!(e.flags & EnvelopeFlag.trailer) &&
|
|
299
|
+
!(e.flags & EnvelopeFlag.endStream),
|
|
300
|
+
)
|
|
301
|
+
.map((e) => inflate(e.flags, e.data, encoding));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Decompress a compressed envelope when the encoding is gzip; otherwise as is. */
|
|
305
|
+
function inflate(
|
|
306
|
+
flags: number,
|
|
307
|
+
data: Uint8Array,
|
|
308
|
+
encoding: string | undefined,
|
|
309
|
+
): Uint8Array {
|
|
310
|
+
if (!(flags & EnvelopeFlag.compressed) || encoding !== "gzip") return data;
|
|
311
|
+
return new Uint8Array(gunzipSync(data));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** gRPC percent-encodes `grpc-message`; a malformed escape must not throw. */
|
|
315
|
+
function safeDecodeURIComponent(value: string): string {
|
|
316
|
+
try {
|
|
317
|
+
return decodeURIComponent(value);
|
|
318
|
+
} catch {
|
|
319
|
+
return value;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DescService } from "@bufbuild/protobuf";
|
|
2
|
+
|
|
3
|
+
import type { HttpRuleHandle } from "../../../entities/plugin/index.js";
|
|
4
|
+
import type { StubHandle } from "../model/types.js";
|
|
5
|
+
import { endpointOf } from "./recorder.js";
|
|
6
|
+
import type { RpcRules } from "./rules.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Record and decode a service's calls without answering them: the request
|
|
10
|
+
* as it leaves, the real backend's messages and status as they come back,
|
|
11
|
+
* or the fault when the connection fails.
|
|
12
|
+
*
|
|
13
|
+
* A call a stub answers is recorded by that stub. Where this rule sits among
|
|
14
|
+
* the stubs does not matter: a request is one exchange however many rules
|
|
15
|
+
* see it, so it lands once either way.
|
|
16
|
+
*/
|
|
17
|
+
export async function recordService(
|
|
18
|
+
rules: RpcRules,
|
|
19
|
+
service: DescService,
|
|
20
|
+
): Promise<StubHandle> {
|
|
21
|
+
const added: HttpRuleHandle[] = [];
|
|
22
|
+
for (const method of service.methods) {
|
|
23
|
+
// A page cannot call the others; there is nothing of theirs to record.
|
|
24
|
+
if (
|
|
25
|
+
method.methodKind !== "unary" &&
|
|
26
|
+
method.methodKind !== "server_streaming"
|
|
27
|
+
)
|
|
28
|
+
continue;
|
|
29
|
+
added.push(
|
|
30
|
+
await rules.add({
|
|
31
|
+
method,
|
|
32
|
+
label: `record ${endpointOf(method)}`,
|
|
33
|
+
options: {},
|
|
34
|
+
anyProtocol: true,
|
|
35
|
+
observe: true,
|
|
36
|
+
respond: () => ({ type: "fallback" }),
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
get hits() {
|
|
42
|
+
return added.reduce((sum, rule) => sum + rule.hits, 0);
|
|
43
|
+
},
|
|
44
|
+
async remove() {
|
|
45
|
+
await Promise.all(added.map((rule) => rule.remove()));
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|