diff --git a/.github/workflows/__all-platform-bundle.yml b/.github/workflows/__all-platform-bundle.yml index 7439f7e16c..99b6b7bb49 100644 --- a/.github/workflows/__all-platform-bundle.yml +++ b/.github/workflows/__all-platform-bundle.yml @@ -32,7 +32,7 @@ jobs: name: All-platform bundle permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__analyze-ref-input.yml b/.github/workflows/__analyze-ref-input.yml index 3047b9d73f..52294f42dd 100644 --- a/.github/workflows/__analyze-ref-input.yml +++ b/.github/workflows/__analyze-ref-input.yml @@ -36,7 +36,7 @@ jobs: name: "Analyze: 'ref' and 'sha' from inputs" permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__autobuild-action.yml b/.github/workflows/__autobuild-action.yml index 497f668a08..080f9893a4 100644 --- a/.github/workflows/__autobuild-action.yml +++ b/.github/workflows/__autobuild-action.yml @@ -36,7 +36,7 @@ jobs: name: autobuild-action permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml index 4ee53ef132..3ccdecda5f 100644 --- a/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml +++ b/.github/workflows/__autobuild-direct-tracing-with-working-dir.yml @@ -38,7 +38,7 @@ jobs: name: Autobuild direct tracing (custom working directory) permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__autobuild-direct-tracing.yml b/.github/workflows/__autobuild-direct-tracing.yml index 964f53fd6b..90084856f6 100644 --- a/.github/workflows/__autobuild-direct-tracing.yml +++ b/.github/workflows/__autobuild-direct-tracing.yml @@ -38,7 +38,7 @@ jobs: name: Autobuild direct tracing permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__build-mode-autobuild.yml b/.github/workflows/__build-mode-autobuild.yml index 3c934442c6..5219e619ca 100644 --- a/.github/workflows/__build-mode-autobuild.yml +++ b/.github/workflows/__build-mode-autobuild.yml @@ -32,7 +32,7 @@ jobs: name: Build mode autobuild permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__build-mode-manual.yml b/.github/workflows/__build-mode-manual.yml index 74252c9966..cae260261f 100644 --- a/.github/workflows/__build-mode-manual.yml +++ b/.github/workflows/__build-mode-manual.yml @@ -32,7 +32,7 @@ jobs: name: Build mode manual permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__build-mode-none.yml b/.github/workflows/__build-mode-none.yml index a9ce123f97..f2cccc577a 100644 --- a/.github/workflows/__build-mode-none.yml +++ b/.github/workflows/__build-mode-none.yml @@ -34,7 +34,7 @@ jobs: name: Build mode none permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__build-mode-rollback.yml b/.github/workflows/__build-mode-rollback.yml index 5457a02d59..3573aff7eb 100644 --- a/.github/workflows/__build-mode-rollback.yml +++ b/.github/workflows/__build-mode-rollback.yml @@ -32,7 +32,7 @@ jobs: name: Build mode rollback permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__cleanup-db-cluster-dir.yml b/.github/workflows/__cleanup-db-cluster-dir.yml index b6abe761a8..1c1afd1fa9 100644 --- a/.github/workflows/__cleanup-db-cluster-dir.yml +++ b/.github/workflows/__cleanup-db-cluster-dir.yml @@ -32,7 +32,7 @@ jobs: name: Clean up database cluster directory permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__config-export.yml b/.github/workflows/__config-export.yml index 76b7b9037d..536060cc45 100644 --- a/.github/workflows/__config-export.yml +++ b/.github/workflows/__config-export.yml @@ -42,7 +42,7 @@ jobs: name: Config export permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__config-input.yml b/.github/workflows/__config-input.yml index 1b419aee7b..6afbf58d75 100644 --- a/.github/workflows/__config-input.yml +++ b/.github/workflows/__config-input.yml @@ -32,7 +32,7 @@ jobs: name: Config input permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__cpp-deptrace-disabled.yml b/.github/workflows/__cpp-deptrace-disabled.yml index 17aa07c8bc..11668c95b0 100644 --- a/.github/workflows/__cpp-deptrace-disabled.yml +++ b/.github/workflows/__cpp-deptrace-disabled.yml @@ -36,7 +36,7 @@ jobs: name: 'C/C++: disabling autoinstalling dependencies (Linux)' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__cpp-deptrace-enabled-on-macos.yml b/.github/workflows/__cpp-deptrace-enabled-on-macos.yml index 60997a9172..d2e417161e 100644 --- a/.github/workflows/__cpp-deptrace-enabled-on-macos.yml +++ b/.github/workflows/__cpp-deptrace-enabled-on-macos.yml @@ -32,7 +32,7 @@ jobs: name: 'C/C++: autoinstalling dependencies is skipped (macOS)' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__cpp-deptrace-enabled.yml b/.github/workflows/__cpp-deptrace-enabled.yml index ce9087f095..87c665b5b8 100644 --- a/.github/workflows/__cpp-deptrace-enabled.yml +++ b/.github/workflows/__cpp-deptrace-enabled.yml @@ -36,7 +36,7 @@ jobs: name: 'C/C++: autoinstalling dependencies (Linux)' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__diagnostics-export.yml b/.github/workflows/__diagnostics-export.yml index 53014cf36c..1137339478 100644 --- a/.github/workflows/__diagnostics-export.yml +++ b/.github/workflows/__diagnostics-export.yml @@ -42,7 +42,7 @@ jobs: name: Diagnostic export permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__export-file-baseline-information.yml b/.github/workflows/__export-file-baseline-information.yml index e6e38ef8a9..2f48ad4c5c 100644 --- a/.github/workflows/__export-file-baseline-information.yml +++ b/.github/workflows/__export-file-baseline-information.yml @@ -36,7 +36,7 @@ jobs: name: Export file baseline information permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__extract-direct-to-toolcache.yml b/.github/workflows/__extract-direct-to-toolcache.yml index 32727c997b..34023f7054 100644 --- a/.github/workflows/__extract-direct-to-toolcache.yml +++ b/.github/workflows/__extract-direct-to-toolcache.yml @@ -36,7 +36,7 @@ jobs: name: Extract directly to toolcache permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__extractor-ram-threads.yml b/.github/workflows/__extractor-ram-threads.yml index 1c38060832..fd2cfd9e88 100644 --- a/.github/workflows/__extractor-ram-threads.yml +++ b/.github/workflows/__extractor-ram-threads.yml @@ -32,7 +32,7 @@ jobs: name: Extractor ram and threads options test permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__go-custom-queries.yml b/.github/workflows/__go-custom-queries.yml index 927b2b88b6..5459ab3f05 100644 --- a/.github/workflows/__go-custom-queries.yml +++ b/.github/workflows/__go-custom-queries.yml @@ -34,7 +34,7 @@ jobs: name: 'Go: Custom queries' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml b/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml index 27f1ac7eb7..7136d70ce8 100644 --- a/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml +++ b/.github/workflows/__go-indirect-tracing-workaround-diagnostic.yml @@ -32,7 +32,7 @@ jobs: name: 'Go: diagnostic when Go is changed after init step' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml b/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml index 471fc64978..341f4f70af 100644 --- a/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml +++ b/.github/workflows/__go-indirect-tracing-workaround-no-file-program.yml @@ -32,7 +32,7 @@ jobs: name: 'Go: diagnostic when `file` is not installed' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__go-indirect-tracing-workaround.yml b/.github/workflows/__go-indirect-tracing-workaround.yml index 62459c3eb6..24c95104db 100644 --- a/.github/workflows/__go-indirect-tracing-workaround.yml +++ b/.github/workflows/__go-indirect-tracing-workaround.yml @@ -32,7 +32,7 @@ jobs: name: 'Go: workaround for indirect tracing' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__go-tracing-autobuilder.yml b/.github/workflows/__go-tracing-autobuilder.yml index 20caf17005..4e3b485ab7 100644 --- a/.github/workflows/__go-tracing-autobuilder.yml +++ b/.github/workflows/__go-tracing-autobuilder.yml @@ -62,7 +62,7 @@ jobs: name: 'Go: tracing with autobuilder step' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__go-tracing-custom-build-steps.yml b/.github/workflows/__go-tracing-custom-build-steps.yml index f5dc2333b7..340f6e8758 100644 --- a/.github/workflows/__go-tracing-custom-build-steps.yml +++ b/.github/workflows/__go-tracing-custom-build-steps.yml @@ -62,7 +62,7 @@ jobs: name: 'Go: tracing with custom build steps' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__go-tracing-legacy-workflow.yml b/.github/workflows/__go-tracing-legacy-workflow.yml index 4baab11718..3af8b1e3a7 100644 --- a/.github/workflows/__go-tracing-legacy-workflow.yml +++ b/.github/workflows/__go-tracing-legacy-workflow.yml @@ -62,7 +62,7 @@ jobs: name: 'Go: tracing with legacy workflow' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__javascript-source-root.yml b/.github/workflows/__javascript-source-root.yml index 04d93978ee..ba2ccd1b5d 100644 --- a/.github/workflows/__javascript-source-root.yml +++ b/.github/workflows/__javascript-source-root.yml @@ -36,7 +36,7 @@ jobs: name: Custom source root permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__job-run-uuid-sarif.yml b/.github/workflows/__job-run-uuid-sarif.yml index 40ff0cb741..1529a72346 100644 --- a/.github/workflows/__job-run-uuid-sarif.yml +++ b/.github/workflows/__job-run-uuid-sarif.yml @@ -32,7 +32,7 @@ jobs: name: Job run UUID added to SARIF permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__language-aliases.yml b/.github/workflows/__language-aliases.yml index a7db4bdf66..0a77e4154c 100644 --- a/.github/workflows/__language-aliases.yml +++ b/.github/workflows/__language-aliases.yml @@ -32,7 +32,7 @@ jobs: name: Language aliases permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__multi-language-autodetect.yml b/.github/workflows/__multi-language-autodetect.yml index 1bab334dcf..5d9cc99749 100644 --- a/.github/workflows/__multi-language-autodetect.yml +++ b/.github/workflows/__multi-language-autodetect.yml @@ -62,7 +62,7 @@ jobs: name: Multi-language repository permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__packaging-codescanning-config-inputs-js.yml b/.github/workflows/__packaging-codescanning-config-inputs-js.yml index 15aeeb4171..bb54bc83a7 100644 --- a/.github/workflows/__packaging-codescanning-config-inputs-js.yml +++ b/.github/workflows/__packaging-codescanning-config-inputs-js.yml @@ -48,7 +48,7 @@ jobs: name: 'Packaging: Config and input passed to the CLI' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__packaging-config-inputs-js.yml b/.github/workflows/__packaging-config-inputs-js.yml index e68085be0c..125ca7a7de 100644 --- a/.github/workflows/__packaging-config-inputs-js.yml +++ b/.github/workflows/__packaging-config-inputs-js.yml @@ -48,7 +48,7 @@ jobs: name: 'Packaging: Config and input' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__packaging-config-js.yml b/.github/workflows/__packaging-config-js.yml index dea5d8eae3..db3e9b7ed5 100644 --- a/.github/workflows/__packaging-config-js.yml +++ b/.github/workflows/__packaging-config-js.yml @@ -48,7 +48,7 @@ jobs: name: 'Packaging: Config file' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__packaging-inputs-js.yml b/.github/workflows/__packaging-inputs-js.yml index cbb91f90dc..c5f4bdc355 100644 --- a/.github/workflows/__packaging-inputs-js.yml +++ b/.github/workflows/__packaging-inputs-js.yml @@ -48,7 +48,7 @@ jobs: name: 'Packaging: Action input' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__remote-config.yml b/.github/workflows/__remote-config.yml index 198fdde921..a615c66ad3 100644 --- a/.github/workflows/__remote-config.yml +++ b/.github/workflows/__remote-config.yml @@ -34,7 +34,7 @@ jobs: name: Remote config file permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__resolve-environment-action.yml b/.github/workflows/__resolve-environment-action.yml index 2c6380323d..632e71e65c 100644 --- a/.github/workflows/__resolve-environment-action.yml +++ b/.github/workflows/__resolve-environment-action.yml @@ -48,7 +48,7 @@ jobs: name: Resolve environment permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__rubocop-multi-language.yml b/.github/workflows/__rubocop-multi-language.yml index 16a6c958d9..dca3140bd5 100644 --- a/.github/workflows/__rubocop-multi-language.yml +++ b/.github/workflows/__rubocop-multi-language.yml @@ -32,7 +32,7 @@ jobs: name: RuboCop multi-language permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__ruby.yml b/.github/workflows/__ruby.yml index 441b51981c..ff9769c01a 100644 --- a/.github/workflows/__ruby.yml +++ b/.github/workflows/__ruby.yml @@ -42,7 +42,7 @@ jobs: name: Ruby analysis permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__split-workflow.yml b/.github/workflows/__split-workflow.yml index ea72bde861..c1e0058c16 100644 --- a/.github/workflows/__split-workflow.yml +++ b/.github/workflows/__split-workflow.yml @@ -42,7 +42,7 @@ jobs: name: Split workflow permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__start-proxy.yml b/.github/workflows/__start-proxy.yml index e66da8bfd9..f2e9b64600 100644 --- a/.github/workflows/__start-proxy.yml +++ b/.github/workflows/__start-proxy.yml @@ -36,7 +36,7 @@ jobs: name: Start proxy permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__submit-sarif-failure.yml b/.github/workflows/__submit-sarif-failure.yml index 1f4300d630..4c37ac0ab4 100644 --- a/.github/workflows/__submit-sarif-failure.yml +++ b/.github/workflows/__submit-sarif-failure.yml @@ -36,7 +36,8 @@ jobs: name: Submit SARIF after failure permissions: contents: read - security-events: write + security-events: write # needed to upload the SARIF file + timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__swift-autobuild.yml b/.github/workflows/__swift-autobuild.yml index 9c17dda79c..7be7c0b339 100644 --- a/.github/workflows/__swift-autobuild.yml +++ b/.github/workflows/__swift-autobuild.yml @@ -32,7 +32,7 @@ jobs: name: Swift analysis using autobuild permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__swift-custom-build.yml b/.github/workflows/__swift-custom-build.yml index ae3d802250..1e6009c66c 100644 --- a/.github/workflows/__swift-custom-build.yml +++ b/.github/workflows/__swift-custom-build.yml @@ -36,7 +36,7 @@ jobs: name: Swift analysis using a custom build command permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__test-autobuild-working-dir.yml b/.github/workflows/__test-autobuild-working-dir.yml index 144ca2173d..52fd8c1ab9 100644 --- a/.github/workflows/__test-autobuild-working-dir.yml +++ b/.github/workflows/__test-autobuild-working-dir.yml @@ -32,7 +32,7 @@ jobs: name: Autobuild working directory permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__test-local-codeql.yml b/.github/workflows/__test-local-codeql.yml index 27792efce0..c14d9543aa 100644 --- a/.github/workflows/__test-local-codeql.yml +++ b/.github/workflows/__test-local-codeql.yml @@ -32,7 +32,7 @@ jobs: name: Local CodeQL bundle permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__test-proxy.yml b/.github/workflows/__test-proxy.yml index 1b2bb68117..f542d4d4d4 100644 --- a/.github/workflows/__test-proxy.yml +++ b/.github/workflows/__test-proxy.yml @@ -34,7 +34,7 @@ jobs: name: Proxy test permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__unset-environment.yml b/.github/workflows/__unset-environment.yml index 3a21054876..82ac0e60b9 100644 --- a/.github/workflows/__unset-environment.yml +++ b/.github/workflows/__unset-environment.yml @@ -34,7 +34,7 @@ jobs: name: Test unsetting environment variables permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__upload-ref-sha-input.yml b/.github/workflows/__upload-ref-sha-input.yml index 7483a83621..a1a5ad4b89 100644 --- a/.github/workflows/__upload-ref-sha-input.yml +++ b/.github/workflows/__upload-ref-sha-input.yml @@ -36,7 +36,7 @@ jobs: name: "Upload-sarif: 'ref' and 'sha' from inputs" permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__with-checkout-path.yml b/.github/workflows/__with-checkout-path.yml index d054ca0cef..524f965175 100644 --- a/.github/workflows/__with-checkout-path.yml +++ b/.github/workflows/__with-checkout-path.yml @@ -36,7 +36,7 @@ jobs: name: Use a custom `checkout_path` permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__zstd-bundle-streaming.yml b/.github/workflows/__zstd-bundle-streaming.yml index e6fad57086..0a5b39d09c 100644 --- a/.github/workflows/__zstd-bundle-streaming.yml +++ b/.github/workflows/__zstd-bundle-streaming.yml @@ -34,7 +34,7 @@ jobs: name: Zstandard bundle (streaming) permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/__zstd-bundle.yml b/.github/workflows/__zstd-bundle.yml index f45268af84..a8065cb977 100644 --- a/.github/workflows/__zstd-bundle.yml +++ b/.github/workflows/__zstd-bundle.yml @@ -36,7 +36,7 @@ jobs: name: Zstandard bundle permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/check-expected-release-files.yml b/.github/workflows/check-expected-release-files.yml index c5d225b410..fd1d7c5ae8 100644 --- a/.github/workflows/check-expected-release-files.yml +++ b/.github/workflows/check-expected-release-files.yml @@ -13,6 +13,9 @@ jobs: check-expected-release-files: runs-on: ubuntu-latest + permissions: + contents: read + steps: - name: Checkout CodeQL Action uses: actions/checkout@v4 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0703ff3676..130ef58839 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,7 +24,7 @@ jobs: versions: ${{ steps.compare.outputs.versions }} permissions: - security-events: write + contents: read steps: - uses: actions/checkout@v4 @@ -80,7 +80,8 @@ jobs: runs-on: ${{ matrix.os }} permissions: - security-events: write + contents: read + security-events: write # needed to upload results steps: - name: Checkout diff --git a/.github/workflows/codescanning-config-cli.yml b/.github/workflows/codescanning-config-cli.yml index c4cd4eeaa8..01795943cb 100644 --- a/.github/workflows/codescanning-config-cli.yml +++ b/.github/workflows/codescanning-config-cli.yml @@ -23,6 +23,11 @@ jobs: code-scanning-config-tests: continue-on-error: true + permissions: + contents: read + packages: read + security-events: read + strategy: fail-fast: false matrix: diff --git a/.github/workflows/debug-artifacts-failure.yml b/.github/workflows/debug-artifacts-failure-safe.yml similarity index 65% rename from .github/workflows/debug-artifacts-failure.yml rename to .github/workflows/debug-artifacts-failure-safe.yml index 4efa196511..108a7a3511 100644 --- a/.github/workflows/debug-artifacts-failure.yml +++ b/.github/workflows/debug-artifacts-failure-safe.yml @@ -19,10 +19,20 @@ on: workflow_dispatch: {} jobs: upload-artifacts: + strategy: + fail-fast: false + matrix: + version: + - stable-v2.20.3 + - default + - linked + - nightly-latest name: Upload debug artifacts after failure in analyze continue-on-error: true env: CODEQL_ACTION_TEST_MODE: true + permissions: + contents: read timeout-minutes: 45 runs-on: ubuntu-latest steps: @@ -34,7 +44,7 @@ jobs: id: prepare-test uses: ./.github/actions/prepare-test with: - version: linked + version: ${{ matrix.version }} - uses: actions/setup-go@v5 with: go-version: ^1.13.1 @@ -58,6 +68,8 @@ jobs: name: Download and check debug artifacts after failure in analyze needs: upload-artifacts timeout-minutes: 45 + permissions: + contents: read runs-on: ubuntu-latest steps: - name: Download all artifacts @@ -66,22 +78,25 @@ jobs: shell: bash run: | LANGUAGES="cpp csharp go java javascript python" - cd "./my-debug-artifacts" - echo "Artifacts from run:" - for language in $LANGUAGES; do - echo "- Checking $language" - if [[ ! -f "my-db-$language-partial.zip" ]] ; then - echo "Missing a partial database bundle for $language" - exit 1 - fi - if [[ ! -d "log" ]] ; then - echo "Missing database initialization logs" - exit 1 - fi - if [[ ! "$language" == "go" ]] && [[ ! -d "$language/log" ]] ; then - echo "Missing logs for $language" - exit 1 - fi + for version in $VERSIONS; do + echo "Artifacts from version $version:" + pushd "./my-debug-artifacts-${version//./}" + for language in $LANGUAGES; do + echo "- Checking $language" + if [[ ! -f "my-db-$language-partial.zip" ]] ; then + echo "Missing a partial database bundle for $language" + exit 1 + fi + if [[ ! -d "log" ]] ; then + echo "Missing database initialization logs" + exit 1 + fi + if [[ ! "$language" == "go" ]] && [[ ! -d "$language/log" ]] ; then + echo "Missing logs for $language" + exit 1 + fi + done + popd done env: GO111MODULE: auto diff --git a/.github/workflows/debug-artifacts.yml b/.github/workflows/debug-artifacts-safe.yml similarity index 91% rename from .github/workflows/debug-artifacts.yml rename to .github/workflows/debug-artifacts-safe.yml index a8cf710085..e508ead92f 100644 --- a/.github/workflows/debug-artifacts.yml +++ b/.github/workflows/debug-artifacts-safe.yml @@ -22,11 +22,7 @@ jobs: fail-fast: false matrix: version: - - stable-v2.15.5 - - stable-v2.16.6 - - stable-v2.17.6 - - stable-v2.18.4 - - stable-v2.19.4 + - stable-v2.20.3 - default - linked - nightly-latest @@ -34,6 +30,8 @@ jobs: env: CODEQL_ACTION_TEST_MODE: true timeout-minutes: 45 + permissions: + contents: read runs-on: ubuntu-latest steps: - name: Check out repository @@ -64,6 +62,8 @@ jobs: name: Download and check debug artifacts needs: upload-artifacts timeout-minutes: 45 + permissions: + contents: read runs-on: ubuntu-latest steps: - name: Download all artifacts @@ -71,7 +71,7 @@ jobs: - name: Check expected artifacts exist shell: bash run: | - VERSIONS="stable-v2.15.5 stable-v2.16.6 stable-v2.17.6 stable-v2.18.4 stable-v2.19.4 default linked nightly-latest" + VERSIONS="stable-v2.20.3 default linked nightly-latest" LANGUAGES="cpp csharp go java javascript python" for version in $VERSIONS; do pushd "./my-debug-artifacts-${version//./}" diff --git a/.github/workflows/expected-queries-runs.yml b/.github/workflows/expected-queries-runs.yml index e76c8920d8..fd75a39a1e 100644 --- a/.github/workflows/expected-queries-runs.yml +++ b/.github/workflows/expected-queries-runs.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - security-events: write + security-events: read steps: - name: Check out repository uses: actions/checkout@v4 diff --git a/.github/workflows/post-release-mergeback.yml b/.github/workflows/post-release-mergeback.yml index f6896fb22b..9b0b35118a 100644 --- a/.github/workflows/post-release-mergeback.yml +++ b/.github/workflows/post-release-mergeback.yml @@ -27,6 +27,9 @@ jobs: BASE_BRANCH: "${{ github.event.inputs.baseBranch || 'main' }}" HEAD_BRANCH: "${{ github.head_ref || github.ref }}" + permissions: + contents: write # needed to create tags and push commits + steps: - name: Dump environment run: env diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index bd406774b8..18ff782489 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 45 permissions: contents: read - security-events: write + security-events: write # needed to upload ESLint results strategy: fail-fast: false @@ -40,6 +40,8 @@ jobs: check-node-modules: if: github.event_name != 'push' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/releases/v') name: Check modules up to date + permissions: + contents: read runs-on: macos-latest timeout-minutes: 45 @@ -51,6 +53,8 @@ jobs: check-file-contents: if: github.event_name != 'push' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/releases/v') name: Check file contents + permissions: + contents: read runs-on: ubuntu-latest timeout-minutes: 45 @@ -81,6 +85,8 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] + permissions: + contents: read runs-on: ${{ matrix.os }} timeout-minutes: 45 @@ -101,6 +107,9 @@ jobs: env: BASE_REF: ${{ github.base_ref }} + permissions: + contents: read + steps: - uses: actions/checkout@v4 - id: head-version diff --git a/.github/workflows/python312-windows.yml b/.github/workflows/python312-windows.yml index da5226dc29..b9eba295b7 100644 --- a/.github/workflows/python312-windows.yml +++ b/.github/workflows/python312-windows.yml @@ -17,6 +17,8 @@ jobs: env: CODEQL_ACTION_TEST_MODE: true timeout-minutes: 45 + permissions: + contents: read runs-on: windows-latest steps: diff --git a/.github/workflows/rebuild.yml b/.github/workflows/rebuild.yml index c2dcb2c690..97cac94fbd 100644 --- a/.github/workflows/rebuild.yml +++ b/.github/workflows/rebuild.yml @@ -11,6 +11,9 @@ jobs: runs-on: ubuntu-latest if: github.event.label.name == 'Rebuild' + permissions: + contents: write # needed to push rebuilt commit + pull-requests: write # needed to comment on the PR steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/test-codeql-bundle-all.yml b/.github/workflows/test-codeql-bundle-all.yml index 2524f58e48..4d08c2117c 100644 --- a/.github/workflows/test-codeql-bundle-all.yml +++ b/.github/workflows/test-codeql-bundle-all.yml @@ -27,7 +27,7 @@ jobs: name: 'CodeQL Bundle All' permissions: contents: read - security-events: write + security-events: read timeout-minutes: 45 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/update-bundle.yml b/.github/workflows/update-bundle.yml index 36a96c7399..73ab6b4141 100644 --- a/.github/workflows/update-bundle.yml +++ b/.github/workflows/update-bundle.yml @@ -17,6 +17,9 @@ jobs: update-bundle: if: github.event.release.prerelease && startsWith(github.event.release.tag_name, 'codeql-bundle-') runs-on: ubuntu-latest + permissions: + contents: write # needed to push commits + pull-requests: write # needed to create pull requests steps: - name: Dump environment run: env diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index 0d24650e05..364dec011f 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -9,6 +9,9 @@ jobs: timeout-minutes: 45 runs-on: macos-latest if: contains(github.event.pull_request.labels.*.name, 'Update dependencies') && (github.event.pull_request.head.repo.full_name == 'github/codeql-action') + permissions: + contents: write # needed to push the updated dependencies + pull-requests: write # needed to comment on the PR steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/update-release-branch.yml b/.github/workflows/update-release-branch.yml index cac2c67b10..71bd817a79 100644 --- a/.github/workflows/update-release-branch.yml +++ b/.github/workflows/update-release-branch.yml @@ -22,6 +22,8 @@ jobs: latest_tag: ${{ steps.versions.outputs.latest_tag }} backport_source_branch: ${{ steps.branches.outputs.backport_source_branch }} backport_target_branches: ${{ steps.branches.outputs.backport_target_branches }} + permissions: + contents: read steps: - uses: actions/checkout@v4 with: @@ -63,6 +65,9 @@ jobs: REPOSITORY: "${{ github.repository }}" MAJOR_VERSION: "${{ needs.prepare.outputs.major_version }}" LATEST_TAG: "${{ needs.prepare.outputs.latest_tag }}" + permissions: + contents: write # needed to push commits + pull-requests: write # needed to create pull request steps: - uses: actions/checkout@v4 with: @@ -114,6 +119,9 @@ jobs: env: SOURCE_BRANCH: ${{ needs.prepare.outputs.backport_source_branch }} TARGET_BRANCH: ${{ matrix.target_branch }} + permissions: + contents: write # needed to push commits + pull-requests: write # needed to create pull request steps: - name: Generate token uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 diff --git a/.github/workflows/update-supported-enterprise-server-versions.yml b/.github/workflows/update-supported-enterprise-server-versions.yml index 6900101006..5eaa167c36 100644 --- a/.github/workflows/update-supported-enterprise-server-versions.yml +++ b/.github/workflows/update-supported-enterprise-server-versions.yml @@ -10,7 +10,10 @@ jobs: name: Update Supported Enterprise Server Versions timeout-minutes: 45 runs-on: ubuntu-latest - if: ${{ github.repository == 'github/codeql-action' }} + if: github.repository == 'github/codeql-action' + permissions: + contents: write # needed to push commits + pull-requests: write # needed to create pull request steps: - name: Setup Python diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e5ebdb6c7..e2f33bc2ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs. +## 3.28.6 - 27 Jan 2025 + +- Re-enable debug artifact upload for CLI versions 2.20.3 or greater. [#2726](https://github.com/github/codeql-action/pull/2726) + ## 3.28.5 - 24 Jan 2025 - Update default CodeQL bundle version to 2.20.3. [#2717](https://github.com/github/codeql-action/pull/2717) diff --git a/lib/analyze-action-post.js b/lib/analyze-action-post.js index a42d975cb1..3b8e501055 100644 --- a/lib/analyze-action-post.js +++ b/lib/analyze-action-post.js @@ -41,6 +41,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(require("@actions/core")); const actionsUtil = __importStar(require("./actions-util")); const api_client_1 = require("./api-client"); +const codeql_1 = require("./codeql"); const config_utils_1 = require("./config-utils"); const debugArtifacts = __importStar(require("./debug-artifacts")); const environment_1 = require("./environment"); @@ -57,7 +58,9 @@ async function runWrapper() { if (process.env[environment_1.EnvVar.INIT_ACTION_HAS_RUN] === "true") { const config = await (0, config_utils_1.getConfig)(actionsUtil.getTemporaryDirectory(), logger); if (config !== undefined) { - await (0, logging_1.withGroup)("Uploading combined SARIF debug artifact", () => debugArtifacts.uploadCombinedSarifArtifacts(logger, config.gitHubVersion.type)); + const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd); + const version = await codeql.getVersion(); + await (0, logging_1.withGroup)("Uploading combined SARIF debug artifact", () => debugArtifacts.uploadCombinedSarifArtifacts(logger, config.gitHubVersion.type, version.version)); } } } diff --git a/lib/analyze-action-post.js.map b/lib/analyze-action-post.js.map index cf32f5ac94..220ccf55fd 100644 --- a/lib/analyze-action-post.js.map +++ b/lib/analyze-action-post.js.map @@ -1 +1 @@ -{"version":3,"file":"analyze-action-post.js","sourceRoot":"","sources":["../src/analyze-action-post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,oDAAsC;AAEtC,4DAA8C;AAC9C,6CAAgD;AAChD,iDAA2C;AAC3C,kEAAoD;AACpD,+CAAuC;AACvC,uCAAwD;AACxD,iCAAoE;AAEpE,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;QAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAEjD,kFAAkF;QAClF,wFAAwF;QACxF,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAM,CAAC,mBAAmB,CAAC,KAAK,MAAM,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAS,EAC5B,WAAW,CAAC,qBAAqB,EAAE,EACnC,MAAM,CACP,CAAC;YACF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,IAAA,mBAAS,EAAC,yCAAyC,EAAE,GAAG,EAAE,CAC9D,cAAc,CAAC,4BAA4B,CACzC,MAAM,EACN,MAAM,CAAC,aAAa,CAAC,IAAI,CAC1B,CACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,CACZ,oCAAoC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAC7D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"analyze-action-post.js","sourceRoot":"","sources":["../src/analyze-action-post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,oDAAsC;AAEtC,4DAA8C;AAC9C,6CAAgD;AAChD,qCAAqC;AACrC,iDAA2C;AAC3C,kEAAoD;AACpD,+CAAuC;AACvC,uCAAwD;AACxD,iCAAoE;AAEpE,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;QAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAEjD,kFAAkF;QAClF,wFAAwF;QACxF,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAM,CAAC,mBAAmB,CAAC,KAAK,MAAM,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAS,EAC5B,WAAW,CAAC,qBAAqB,EAAE,EACnC,MAAM,CACP,CAAC;YACF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAS,EAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBACjD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;gBAC1C,MAAM,IAAA,mBAAS,EAAC,yCAAyC,EAAE,GAAG,EAAE,CAC9D,cAAc,CAAC,4BAA4B,CACzC,MAAM,EACN,MAAM,CAAC,aAAa,CAAC,IAAI,EACzB,OAAO,CAAC,OAAO,CAChB,CACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,CACZ,oCAAoC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAC7D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"} \ No newline at end of file diff --git a/lib/debug-artifacts.js b/lib/debug-artifacts.js index 1724935891..cf5fadc8ca 100644 --- a/lib/debug-artifacts.js +++ b/lib/debug-artifacts.js @@ -53,6 +53,7 @@ const analyze_1 = require("./analyze"); const codeql_1 = require("./codeql"); const environment_1 = require("./environment"); const logging_1 = require("./logging"); +const tools_features_1 = require("./tools-features"); const util_1 = require("./util"); function sanitizeArtifactName(name) { return name.replace(/[^a-zA-Z0-9_\\-]+/g, ""); @@ -61,7 +62,7 @@ function sanitizeArtifactName(name) { * Upload Actions SARIF artifacts for debugging when CODEQL_ACTION_DEBUG_COMBINED_SARIF * environment variable is set */ -async function uploadCombinedSarifArtifacts(logger, gitHubVariant) { +async function uploadCombinedSarifArtifacts(logger, gitHubVariant, codeQlVersion) { const tempDir = (0, actions_util_1.getTemporaryDirectory)(); // Upload Actions SARIF artifacts for debugging when environment variable is set if (process.env["CODEQL_ACTION_DEBUG_COMBINED_SARIF"] === "true") { @@ -80,7 +81,7 @@ async function uploadCombinedSarifArtifacts(logger, gitHubVariant) { } } try { - await uploadDebugArtifacts(logger, toUpload, baseTempDir, "combined-sarif-artifacts", gitHubVariant); + await uploadDebugArtifacts(logger, toUpload, baseTempDir, "combined-sarif-artifacts", gitHubVariant, codeQlVersion); } catch (e) { logger.warning(`Failed to upload combined SARIF files as Actions debugging artifact. Reason: ${(0, util_1.getErrorMessage)(e)}`); @@ -140,7 +141,7 @@ async function tryBundleDatabase(config, language, logger) { * * Logs and suppresses any errors that occur. */ -async function tryUploadAllAvailableDebugArtifacts(config, logger) { +async function tryUploadAllAvailableDebugArtifacts(config, logger, codeQlVersion) { const filesToUpload = []; try { for (const language of config.languages) { @@ -180,20 +181,23 @@ async function tryUploadAllAvailableDebugArtifacts(config, logger) { return; } try { - await (0, logging_1.withGroup)("Uploading debug artifacts", async () => uploadDebugArtifacts(logger, filesToUpload, config.dbLocation, config.debugArtifactName, config.gitHubVersion.type)); + await (0, logging_1.withGroup)("Uploading debug artifacts", async () => uploadDebugArtifacts(logger, filesToUpload, config.dbLocation, config.debugArtifactName, config.gitHubVersion.type, codeQlVersion)); } catch (e) { logger.warning(`Failed to upload debug artifacts. Reason: ${(0, util_1.getErrorMessage)(e)}`); } } -async function uploadDebugArtifacts(logger, toUpload, rootDir, artifactName, ghVariant) { +async function uploadDebugArtifacts(logger, toUpload, rootDir, artifactName, ghVariant, codeQlVersion) { if (toUpload.length === 0) { - return; + return "no-artifacts-to-upload"; + } + const uploadSupported = (0, tools_features_1.isSafeArtifactUpload)(codeQlVersion); + if (!uploadSupported) { + core.info(`Skipping debug artifact upload because the current CLI does not support safe upload. Please upgrade to CLI v${tools_features_1.SafeArtifactUploadVersion} or later.`); + return "upload-not-supported"; } - logger.info("Uploading debug artifacts is temporarily disabled"); - return; let suffix = ""; - const matrix = (0, actions_util_1.getRequiredInput)("matrix"); + const matrix = (0, actions_util_1.getOptionalInput)("matrix"); if (matrix) { try { for (const [, matrixVal] of Object.entries(JSON.parse(matrix)).sort()) @@ -209,10 +213,12 @@ async function uploadDebugArtifacts(logger, toUpload, rootDir, artifactName, ghV // ensure we don't keep the debug artifacts around for too long since they can be large. retentionDays: 7, }); + return "upload-successful"; } catch (e) { // A failure to upload debug artifacts should not fail the entire action. core.warning(`Failed to upload debug artifacts: ${e}`); + return "upload-failed"; } } // `@actions/artifact@v2` is not yet supported on GHES so the legacy version of the client will be used on GHES diff --git a/lib/debug-artifacts.js.map b/lib/debug-artifacts.js.map index 3f4d6b322a..9f9115967c 100644 --- a/lib/debug-artifacts.js.map +++ b/lib/debug-artifacts.js.map @@ -1 +1 @@ -{"version":3,"file":"debug-artifacts.js","sourceRoot":"","sources":["../src/debug-artifacts.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"debug-artifacts.js","sourceRoot":"","sources":["../src/debug-artifacts.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/debug-artifacts.test.js b/lib/debug-artifacts.test.js index b80b38b70d..4df433b6c7 100644 --- a/lib/debug-artifacts.test.js +++ b/lib/debug-artifacts.test.js @@ -46,9 +46,47 @@ const util_1 = require("./util"); t.deepEqual(debugArtifacts.sanitizeArtifactName("hello===123"), "hello123"); t.deepEqual(debugArtifacts.sanitizeArtifactName("*m)a&n^y%i££n+v!a:l[i]d"), "manyinvalid"); }); -(0, ava_1.default)("uploadDebugArtifacts", async (t) => { +// These next tests check the correctness of the logic to determine whether or not +// artifacts are uploaded in debug mode. Since it's not easy to mock the actual +// call to upload an artifact, we just check that we get an "upload-failed" result, +// instead of actually uploading the artifact. +// +// For tests where we expect artifact upload to be blocked, we check for a different +// response from the function. +(0, ava_1.default)("uploadDebugArtifacts when artifacts empty should emit 'no-artifacts-to-upload'", async (t) => { // Test that no error is thrown if artifacts list is empty. const logger = (0, logging_1.getActionsLogger)(); - await t.notThrowsAsync(debugArtifacts.uploadDebugArtifacts(logger, [], "rootDir", "artifactName", util_1.GitHubVariant.DOTCOM)); + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts(logger, [], "i-dont-exist", "artifactName", util_1.GitHubVariant.DOTCOM, undefined); + t.is(uploaded, "no-artifacts-to-upload", "Should not have uploaded any artifacts"); + }); +}); +(0, ava_1.default)("uploadDebugArtifacts when no codeql version is used should invoke artifact upload", async (t) => { + // Test that the artifact is uploaded. + const logger = (0, logging_1.getActionsLogger)(); + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts(logger, ["hucairz"], "i-dont-exist", "artifactName", util_1.GitHubVariant.DOTCOM, undefined); + t.is(uploaded, + // The failure is expected since we don't want to actually upload any artifacts in unit tests. + "upload-failed", "Expect failure to upload artifacts since root dir does not exist"); + }); +}); +(0, ava_1.default)("uploadDebugArtifacts when new codeql version is used should invoke artifact upload", async (t) => { + // Test that the artifact is uploaded. + const logger = (0, logging_1.getActionsLogger)(); + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts(logger, ["hucairz"], "i-dont-exist", "artifactName", util_1.GitHubVariant.DOTCOM, "2.20.3"); + t.is(uploaded, + // The failure is expected since we don't want to actually upload any artifacts in unit tests. + "upload-failed", "Expect failure to upload artifacts since root dir does not exist"); + }); +}); +(0, ava_1.default)("uploadDebugArtifacts when old codeql is used should avoid trying to upload artifacts", async (t) => { + // Test that the artifact is not uploaded. + const logger = (0, logging_1.getActionsLogger)(); + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts(logger, ["hucairz"], "i-dont-exist", "artifactName", util_1.GitHubVariant.DOTCOM, "2.20.2"); + t.is(uploaded, "upload-not-supported", "Expected artifact upload to be blocked because of old CodeQL version"); + }); }); //# sourceMappingURL=debug-artifacts.test.js.map \ No newline at end of file diff --git a/lib/debug-artifacts.test.js.map b/lib/debug-artifacts.test.js.map index c4f7ca2aae..0facecaa66 100644 --- a/lib/debug-artifacts.test.js.map +++ b/lib/debug-artifacts.test.js.map @@ -1 +1 @@ -{"version":3,"file":"debug-artifacts.test.js","sourceRoot":"","sources":["../src/debug-artifacts.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAuB;AAEvB,kEAAoD;AACpD,uCAA6C;AAC7C,iCAAuC;AAEvC,IAAA,aAAI,EAAC,sBAAsB,EAAE,CAAC,CAAC,EAAE,EAAE;IACjC,CAAC,CAAC,SAAS,CACT,cAAc,CAAC,oBAAoB,CAAC,cAAc,CAAC,EACnD,cAAc,CACf,CAAC;IACF,CAAC,CAAC,SAAS,CACT,cAAc,CAAC,oBAAoB,CAAC,cAAc,CAAC,EACnD,YAAY,CACb,CAAC;IACF,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,oBAAoB,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC,CAAC;IAC5E,CAAC,CAAC,SAAS,CACT,cAAc,CAAC,oBAAoB,CAAC,yBAAyB,CAAC,EAC9D,aAAa,CACd,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACvC,2DAA2D;IAC3D,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAClC,MAAM,CAAC,CAAC,cAAc,CACpB,cAAc,CAAC,oBAAoB,CACjC,MAAM,EACN,EAAE,EACF,SAAS,EACT,cAAc,EACd,oBAAa,CAAC,MAAM,CACrB,CACF,CAAC;AACJ,CAAC,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"debug-artifacts.test.js","sourceRoot":"","sources":["../src/debug-artifacts.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/init-action-post-helper.js b/lib/init-action-post-helper.js index 3ff4e5f635..22155bccba 100644 --- a/lib/init-action-post-helper.js +++ b/lib/init-action-post-helper.js @@ -142,7 +142,9 @@ async function run(uploadAllAvailableDebugArtifacts, printDebugLogs, config, rep // Upload appropriate Actions artifacts for debugging if (config.debugMode) { logger.info("Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts..."); - await uploadAllAvailableDebugArtifacts(config, logger, features); + const codeql = await (0, codeql_1.getCodeQL)(config.codeQLCmd); + const version = await codeql.getVersion(); + await uploadAllAvailableDebugArtifacts(config, logger, version.version); await printDebugLogs(config); } if (actionsUtil.isSelfHostedRunner()) { diff --git a/lib/init-action-post-helper.js.map b/lib/init-action-post-helper.js.map index 8c1fae2038..96d4c64df1 100644 --- a/lib/init-action-post-helper.js.map +++ b/lib/init-action-post-helper.js.map @@ -1 +1 @@ -{"version":3,"file":"init-action-post-helper.js","sourceRoot":"","sources":["../src/init-action-post-helper.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"init-action-post-helper.js","sourceRoot":"","sources":["../src/init-action-post-helper.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/start-proxy-action.js b/lib/start-proxy-action.js index 6a2030ea9d..deb61dc07c 100644 --- a/lib/start-proxy-action.js +++ b/lib/start-proxy-action.js @@ -39,8 +39,8 @@ const core = __importStar(require("@actions/core")); const toolcache = __importStar(require("@actions/tool-cache")); const node_forge_1 = require("node-forge"); const actionsUtil = __importStar(require("./actions-util")); -const languages_1 = require("./languages"); const logging_1 = require("./logging"); +const start_proxy_1 = require("./start-proxy"); const util = __importStar(require("./util")); const UPDATEJOB_PROXY = "update-job-proxy"; const UPDATEJOB_PROXY_VERSION = "v2.0.20241023203727"; @@ -48,19 +48,6 @@ const UPDATEJOB_PROXY_URL_PREFIX = "https://github.com/github/codeql-action/rele const PROXY_USER = "proxy_user"; const KEY_SIZE = 2048; const KEY_EXPIRY_YEARS = 2; -const LANGUAGE_TO_REGISTRY_TYPE = { - java: "maven_repository", - csharp: "nuget_feed", - javascript: "npm_registry", - python: "python_index", - ruby: "rubygems_server", - rust: "cargo_registry", - // We do not have an established proxy type for these languages, thus leaving empty. - actions: "", - cpp: "", - go: "", - swift: "", -}; const CERT_SUBJECT = [ { name: "commonName", @@ -112,7 +99,7 @@ async function runWrapper() { const proxyLogFilePath = path.resolve(tempDir, "proxy.log"); core.saveState("proxy-log-file", proxyLogFilePath); // Get the configuration options - const credentials = getCredentials(logger); + const credentials = (0, start_proxy_1.getCredentials)(logger, actionsUtil.getOptionalInput("registry_secrets"), actionsUtil.getOptionalInput("registries_credentials"), actionsUtil.getOptionalInput("language")); logger.info(`Credentials loaded for the following registries:\n ${credentials .map((c) => credentialToStr(c)) .join("\n")}`); @@ -178,53 +165,6 @@ async function startProxy(binPath, config, logFilePath, logger) { core.setFailed(`start-proxy action failed: ${util.getErrorMessage(error)}`); } } -// getCredentials returns registry credentials from action inputs. -// It prefers `registries_credentials` over `registry_secrets`. -// If neither is set, it returns an empty array. -function getCredentials(logger) { - const registriesCredentials = actionsUtil.getOptionalInput("registries_credentials"); - const registrySecrets = actionsUtil.getOptionalInput("registry_secrets"); - const languageString = actionsUtil.getOptionalInput("language"); - const language = languageString ? (0, languages_1.parseLanguage)(languageString) : undefined; - const registryTypeForLanguage = language - ? LANGUAGE_TO_REGISTRY_TYPE[language] - : undefined; - let credentialsStr; - if (registriesCredentials !== undefined) { - logger.info(`Using registries_credentials input.`); - credentialsStr = Buffer.from(registriesCredentials, "base64").toString(); - } - else if (registrySecrets !== undefined) { - logger.info(`Using registry_secrets input.`); - credentialsStr = registrySecrets; - } - else { - logger.info(`No credentials defined.`); - return []; - } - // Parse and validate the credentials - const parsed = JSON.parse(credentialsStr); - const out = []; - for (const e of parsed) { - if (e.url === undefined && e.host === undefined) { - throw new Error("Invalid credentials - must specify host or url"); - } - // Filter credentials based on language if specified. `type` is the registry type. - // E.g., "maven_feed" for Java/Kotlin, "nuget_repository" for C#. - if (e.type !== registryTypeForLanguage) { - continue; - } - out.push({ - type: e.type, - host: e.host, - url: e.url, - username: e.username, - password: e.password, - token: e.token, - }); - } - return out; -} // getProxyAuth returns the authentication information for the proxy itself. function getProxyAuth() { const proxy_password = actionsUtil.getOptionalInput("proxy_password"); diff --git a/lib/start-proxy-action.js.map b/lib/start-proxy-action.js.map index 5e4bbc8f79..c58df44d37 100644 --- a/lib/start-proxy-action.js.map +++ b/lib/start-proxy-action.js.map @@ -1 +1 @@ -{"version":3,"file":"start-proxy-action.js","sourceRoot":"","sources":["../src/start-proxy-action.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"start-proxy-action.js","sourceRoot":"","sources":["../src/start-proxy-action.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/start-proxy.js b/lib/start-proxy.js new file mode 100644 index 0000000000..9bbcaeba9c --- /dev/null +++ b/lib/start-proxy.js @@ -0,0 +1,83 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getCredentials = getCredentials; +const languages_1 = require("./languages"); +const util_1 = require("./util"); +const LANGUAGE_TO_REGISTRY_TYPE = { + java: "maven_repository", + csharp: "nuget_feed", + javascript: "npm_registry", + python: "python_index", + ruby: "rubygems_server", + rust: "cargo_registry", + // We do not have an established proxy type for these languages, thus leaving empty. + actions: "", + cpp: "", + go: "", + swift: "", +}; +// getCredentials returns registry credentials from action inputs. +// It prefers `registries_credentials` over `registry_secrets`. +// If neither is set, it returns an empty array. +function getCredentials(logger, registrySecrets, registriesCredentials, languageString) { + const language = languageString ? (0, languages_1.parseLanguage)(languageString) : undefined; + const registryTypeForLanguage = language + ? LANGUAGE_TO_REGISTRY_TYPE[language] + : undefined; + let credentialsStr; + if (registriesCredentials !== undefined) { + logger.info(`Using registries_credentials input.`); + credentialsStr = Buffer.from(registriesCredentials, "base64").toString(); + } + else if (registrySecrets !== undefined) { + logger.info(`Using registry_secrets input.`); + credentialsStr = registrySecrets; + } + else { + logger.info(`No credentials defined.`); + return []; + } + // Parse and validate the credentials + let parsed; + try { + parsed = JSON.parse(credentialsStr); + } + catch { + // Don't log the error since it might contain sensitive information. + logger.error("Failed to parse the credentials data."); + throw new util_1.ConfigurationError("Invalid credentials format."); + } + const out = []; + for (const e of parsed) { + if (e.url === undefined && e.host === undefined) { + // The proxy needs one of these to work. If both are defined, the url has the precedence. + throw new util_1.ConfigurationError("Invalid credentials - must specify host or url"); + } + // Filter credentials based on language if specified. `type` is the registry type. + // E.g., "maven_feed" for Java/Kotlin, "nuget_repository" for C#. + if (registryTypeForLanguage && e.type !== registryTypeForLanguage) { + continue; + } + const isPrintable = (str) => { + return str ? /^[\x20-\x7E]*$/.test(str) : true; + }; + if (!isPrintable(e.type) || + !isPrintable(e.host) || + !isPrintable(e.url) || + !isPrintable(e.username) || + !isPrintable(e.password) || + !isPrintable(e.token)) { + throw new util_1.ConfigurationError("Invalid credentials - fields must contain only printable characters"); + } + out.push({ + type: e.type, + host: e.host, + url: e.url, + username: e.username, + password: e.password, + token: e.token, + }); + } + return out; +} +//# sourceMappingURL=start-proxy.js.map \ No newline at end of file diff --git a/lib/start-proxy.js.map b/lib/start-proxy.js.map new file mode 100644 index 0000000000..031deff1ab --- /dev/null +++ b/lib/start-proxy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"start-proxy.js","sourceRoot":"","sources":["../src/start-proxy.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/start-proxy.test.js b/lib/start-proxy.test.js new file mode 100644 index 0000000000..b4d53aad87 --- /dev/null +++ b/lib/start-proxy.test.js @@ -0,0 +1,99 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const ava_1 = __importDefault(require("ava")); +const logging_1 = require("./logging"); +const startProxyExports = __importStar(require("./start-proxy")); +const testing_utils_1 = require("./testing-utils"); +(0, testing_utils_1.setupTests)(ava_1.default); +(0, ava_1.default)("getCredentials prefers registriesCredentials over registrySecrets", async (t) => { + const registryCredentials = Buffer.from(JSON.stringify([ + { type: "npm_registry", host: "npm.pkg.github.com", token: "abc" }, + ])).toString("base64"); + const registrySecrets = JSON.stringify([ + { type: "npm_registry", host: "registry.npmjs.org", token: "def" }, + ]); + const credentials = startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), registrySecrets, registryCredentials, undefined); + t.is(credentials.length, 1); + t.is(credentials[0].host, "npm.pkg.github.com"); +}); +(0, ava_1.default)("getCredentials throws error when credential missing host and url", async (t) => { + const registryCredentials = Buffer.from(JSON.stringify([{ type: "npm_registry", token: "abc" }])).toString("base64"); + t.throws(() => startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, registryCredentials, undefined), { + message: "Invalid credentials - must specify host or url", + }); +}); +(0, ava_1.default)("getCredentials filters by language when specified", async (t) => { + const mixedCredentials = [ + { type: "npm_registry", host: "npm.pkg.github.com", token: "abc" }, + { type: "maven_repository", host: "maven.pkg.github.com", token: "def" }, + { type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" }, + ]; + const credentials = startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, Buffer.from(JSON.stringify(mixedCredentials)).toString("base64"), "java"); + t.is(credentials.length, 1); + t.is(credentials[0].type, "maven_repository"); +}); +(0, ava_1.default)("getCredentials returns all credentials when no language specified", async (t) => { + const mixedCredentials = [ + { type: "npm_registry", host: "npm.pkg.github.com", token: "abc" }, + { type: "maven_repository", host: "maven.pkg.github.com", token: "def" }, + { type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" }, + ]; + const credentialsInput = Buffer.from(JSON.stringify(mixedCredentials)).toString("base64"); + const credentials = startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, credentialsInput, undefined); + t.is(credentials.length, 3); +}); +(0, ava_1.default)("getCredentials throws an error when non-printable characters are used", async (t) => { + const invalidCredentials = [ + { type: "nuget_feed", host: "1nuget.pkg.github.com", token: "abc\u0000" }, // Non-printable character in token + { type: "nuget_feed", host: "2nuget.pkg.github.com\u0001" }, // Non-printable character in host + { + type: "nuget_feed", + host: "3nuget.pkg.github.com", + password: "ghi\u0002", + }, // Non-printable character in password + { type: "nuget_feed", host: "4nuget.pkg.github.com", password: "ghi\x00" }, // Non-printable character in password + ]; + for (const invalidCredential of invalidCredentials) { + const credentialsInput = Buffer.from(JSON.stringify([invalidCredential])).toString("base64"); + t.throws(() => startProxyExports.getCredentials((0, logging_1.getRunnerLogger)(true), undefined, credentialsInput, undefined), { + message: "Invalid credentials - fields must contain only printable characters", + }); + } +}); +//# sourceMappingURL=start-proxy.test.js.map \ No newline at end of file diff --git a/lib/start-proxy.test.js.map b/lib/start-proxy.test.js.map new file mode 100644 index 0000000000..c9ca771a5c --- /dev/null +++ b/lib/start-proxy.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"start-proxy.test.js","sourceRoot":"","sources":["../src/start-proxy.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAuB;AAEvB,uCAA4C;AAC5C,iEAAmD;AACnD,mDAA6C;AAE7C,IAAA,0BAAU,EAAC,aAAI,CAAC,CAAC;AAEjB,IAAA,aAAI,EAAC,mEAAmE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACpF,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CACrC,IAAI,CAAC,SAAS,CAAC;QACb,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE;KACnE,CAAC,CACH,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrB,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC;QACrC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE;KACnE,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,iBAAiB,CAAC,cAAc,CAClD,IAAA,yBAAe,EAAC,IAAI,CAAC,EACrB,eAAe,EACf,mBAAmB,EACnB,SAAS,CACV,CAAC;IACF,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,kEAAkE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACnF,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CACrC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CACzD,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErB,CAAC,CAAC,MAAM,CACN,GAAG,EAAE,CACH,iBAAiB,CAAC,cAAc,CAC9B,IAAA,yBAAe,EAAC,IAAI,CAAC,EACrB,SAAS,EACT,mBAAmB,EACnB,SAAS,CACV,EACH;QACE,OAAO,EAAE,gDAAgD;KAC1D,CACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,mDAAmD,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACpE,MAAM,gBAAgB,GAAG;QACvB,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE;QAClE,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK,EAAE;QACxE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK,EAAE;KACnE,CAAC;IAEF,MAAM,WAAW,GAAG,iBAAiB,CAAC,cAAc,CAClD,IAAA,yBAAe,EAAC,IAAI,CAAC,EACrB,SAAS,EACT,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAChE,MAAM,CACP,CAAC;IACF,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,mEAAmE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACpF,MAAM,gBAAgB,GAAG;QACvB,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE;QAClE,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK,EAAE;QACxE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK,EAAE;KACnE,CAAC;IACF,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAClC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CACjC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErB,MAAM,WAAW,GAAG,iBAAiB,CAAC,cAAc,CAClD,IAAA,yBAAe,EAAC,IAAI,CAAC,EACrB,SAAS,EACT,gBAAgB,EAChB,SAAS,CACV,CAAC;IACF,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEH,IAAA,aAAI,EAAC,uEAAuE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACxF,MAAM,kBAAkB,GAAG;QACzB,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,mCAAmC;QAC9G,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,6BAA6B,EAAE,EAAE,kCAAkC;QAC/F;YACE,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,uBAAuB;YAC7B,QAAQ,EAAE,WAAW;SACtB,EAAE,sCAAsC;QACzC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,uBAAuB,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,sCAAsC;KACnH,CAAC;IAEF,KAAK,MAAM,iBAAiB,IAAI,kBAAkB,EAAE,CAAC;QACnD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAClC,IAAI,CAAC,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAAC,CACpC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAErB,CAAC,CAAC,MAAM,CACN,GAAG,EAAE,CACH,iBAAiB,CAAC,cAAc,CAC9B,IAAA,yBAAe,EAAC,IAAI,CAAC,EACrB,SAAS,EACT,gBAAgB,EAChB,SAAS,CACV,EACH;YACE,OAAO,EACL,qEAAqE;SACxE,CACF,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/lib/tools-features.js b/lib/tools-features.js index 7cb8e43786..277bddfe85 100644 --- a/lib/tools-features.js +++ b/lib/tools-features.js @@ -1,7 +1,42 @@ "use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); Object.defineProperty(exports, "__esModule", { value: true }); -exports.ToolsFeature = void 0; +exports.SafeArtifactUploadVersion = exports.ToolsFeature = void 0; exports.isSupportedToolsFeature = isSupportedToolsFeature; +exports.isSafeArtifactUpload = isSafeArtifactUpload; +const semver = __importStar(require("semver")); var ToolsFeature; (function (ToolsFeature) { ToolsFeature["AnalysisSummaryV2IsDefault"] = "analysisSummaryV2Default"; @@ -25,4 +60,20 @@ var ToolsFeature; function isSupportedToolsFeature(versionInfo, feature) { return !!versionInfo.features && versionInfo.features[feature]; } +exports.SafeArtifactUploadVersion = "2.20.3"; +/** + * The first version of the CodeQL CLI where artifact upload is safe to use + * for failed runs. This is not really a feature flag, but it is easiest to + * model the behavior as a feature flag. + * + * This was not captured in a tools feature, so we need to use semver. + * + * @param codeQlVersion The version of the CodeQL CLI to check. If not provided, it is assumed to be safe. + * @returns True if artifact upload is safe to use for failed runs or false otherwise. + */ +function isSafeArtifactUpload(codeQlVersion) { + return !codeQlVersion + ? true + : semver.gte(codeQlVersion, exports.SafeArtifactUploadVersion); +} //# sourceMappingURL=tools-features.js.map \ No newline at end of file diff --git a/lib/tools-features.js.map b/lib/tools-features.js.map index be559b0f74..7a0c041462 100644 --- a/lib/tools-features.js.map +++ b/lib/tools-features.js.map @@ -1 +1 @@ -{"version":3,"file":"tools-features.js","sourceRoot":"","sources":["../src/tools-features.ts"],"names":[],"mappings":";;;AAsBA,0DAKC;AAzBD,IAAY,YAWX;AAXD,WAAY,YAAY;IACtB,uEAAuD,CAAA;IACvD,mDAAmC,CAAA;IACnC,qHAAqG,CAAA;IACrG,+FAA+E,CAAA;IAC/E,yFAAyE,CAAA;IACzE,iEAAiD,CAAA;IACjD,qEAAqD,CAAA;IACrD,mFAAmE,CAAA;IACnE,iDAAiC,CAAA;IACjC,uFAAuE,CAAA;AACzE,CAAC,EAXW,YAAY,4BAAZ,YAAY,QAWvB;AAED;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,WAAwB,EACxB,OAAqB;IAErB,OAAO,CAAC,CAAC,WAAW,CAAC,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACjE,CAAC"} \ No newline at end of file +{"version":3,"file":"tools-features.js","sourceRoot":"","sources":["../src/tools-features.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,0DAKC;AAcD,oDAIC;AA/CD,+CAAiC;AAIjC,IAAY,YAWX;AAXD,WAAY,YAAY;IACtB,uEAAuD,CAAA;IACvD,mDAAmC,CAAA;IACnC,qHAAqG,CAAA;IACrG,+FAA+E,CAAA;IAC/E,yFAAyE,CAAA;IACzE,iEAAiD,CAAA;IACjD,qEAAqD,CAAA;IACrD,mFAAmE,CAAA;IACnE,iDAAiC,CAAA;IACjC,uFAAuE,CAAA;AACzE,CAAC,EAXW,YAAY,4BAAZ,YAAY,QAWvB;AAED;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,WAAwB,EACxB,OAAqB;IAErB,OAAO,CAAC,CAAC,WAAW,CAAC,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACjE,CAAC;AAEY,QAAA,yBAAyB,GAAG,QAAQ,CAAC;AAElD;;;;;;;;;GASG;AACH,SAAgB,oBAAoB,CAAC,aAAsB;IACzD,OAAO,CAAC,aAAa;QACnB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,iCAAyB,CAAC,CAAC;AAC3D,CAAC"} \ No newline at end of file diff --git a/lib/upload-sarif-action-post.js b/lib/upload-sarif-action-post.js index a5a8d5c245..77f2409b94 100644 --- a/lib/upload-sarif-action-post.js +++ b/lib/upload-sarif-action-post.js @@ -59,7 +59,10 @@ async function runWrapper() { core.warning(`Did not upload debug artifacts because cannot determine the GitHub variant running.`); return; } - await (0, logging_1.withGroup)("Uploading combined SARIF debug artifact", () => debugArtifacts.uploadCombinedSarifArtifacts(logger, gitHubVersion.type)); + await (0, logging_1.withGroup)("Uploading combined SARIF debug artifact", () => debugArtifacts.uploadCombinedSarifArtifacts(logger, gitHubVersion.type, + // The codeqlVersion is not applicable for uploading non-codeql sarif. + // We can assume all versions are safe to upload. + undefined)); } } catch (error) { diff --git a/lib/upload-sarif-action-post.js.map b/lib/upload-sarif-action-post.js.map index 85152da16c..17da641cdf 100644 --- a/lib/upload-sarif-action-post.js.map +++ b/lib/upload-sarif-action-post.js.map @@ -1 +1 @@ -{"version":3,"file":"upload-sarif-action-post.js","sourceRoot":"","sources":["../src/upload-sarif-action-post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,oDAAsC;AAEtC,4DAA8C;AAC9C,6CAAgD;AAChD,kEAAoD;AACpD,+CAAuC;AACvC,uCAAwD;AACxD,iCAAoE;AAEpE,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,6CAA6C;QAC7C,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;QAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAEjD,kFAAkF;QAClF,mFAAmF;QACnF,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAM,CAAC,mBAAmB,CAAC,KAAK,MAAM,EAAE,CAAC;YACvD,IAAI,aAAa,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACrC,IAAI,CAAC,OAAO,CACV,qFAAqF,CACtF,CAAC;gBACF,OAAO;YACT,CAAC;YACD,MAAM,IAAA,mBAAS,EAAC,yCAAyC,EAAE,GAAG,EAAE,CAC9D,cAAc,CAAC,4BAA4B,CAAC,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,CACxE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,CACZ,yCAAyC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"upload-sarif-action-post.js","sourceRoot":"","sources":["../src/upload-sarif-action-post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,oDAAsC;AAEtC,4DAA8C;AAC9C,6CAAgD;AAChD,kEAAoD;AACpD,+CAAuC;AACvC,uCAAwD;AACxD,iCAAoE;AAEpE,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,6CAA6C;QAC7C,WAAW,CAAC,aAAa,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;QAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAEjD,kFAAkF;QAClF,mFAAmF;QACnF,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAM,CAAC,mBAAmB,CAAC,KAAK,MAAM,EAAE,CAAC;YACvD,IAAI,aAAa,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACrC,IAAI,CAAC,OAAO,CACV,qFAAqF,CACtF,CAAC;gBACF,OAAO;YACT,CAAC;YACD,MAAM,IAAA,mBAAS,EAAC,yCAAyC,EAAE,GAAG,EAAE,CAC9D,cAAc,CAAC,4BAA4B,CACzC,MAAM,EACN,aAAa,CAAC,IAAI;YAClB,sEAAsE;YACtE,iDAAiD;YACjD,SAAS,CACV,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,CACZ,yCAAyC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"} \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 06f2758975..1f1c8a4a58 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "3.28.5", + "version": "3.28.6", "lockfileVersion": 3, "requires": true, "packages": { @@ -638,9 +638,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { @@ -793,6 +793,24 @@ "node": ">= 14" } }, + "node_modules/@mswjs/interceptors": { + "version": "0.37.5", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.5.tgz", + "integrity": "sha512-AAwRb5vXFcY4L+FvZ7LZusDuZ0vEe0Zm8ohn1FM6/X7A3bj4mqmkAcGRWuvC2JwSygNwHAAmMnAI73vPHeqsHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "license": "MIT", @@ -1061,6 +1079,31 @@ "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", "license": "MIT" }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1292,17 +1335,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz", - "integrity": "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", + "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/type-utils": "8.21.0", - "@typescript-eslint/utils": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/type-utils": "8.22.0", + "@typescript-eslint/utils": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1322,14 +1365,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", - "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1340,9 +1383,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", - "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "dev": true, "license": "MIT", "engines": { @@ -1354,14 +1397,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", - "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1381,16 +1424,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz", - "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", + "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/typescript-estree": "8.21.0" + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1405,13 +1448,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", - "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1475,16 +1518,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.21.0.tgz", - "integrity": "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", + "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/typescript-estree": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4" }, "engines": { @@ -1500,14 +1543,14 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", - "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1518,9 +1561,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", - "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "dev": true, "license": "MIT", "engines": { @@ -1532,14 +1575,14 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", - "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1559,13 +1602,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", - "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1647,14 +1690,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz", - "integrity": "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", + "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.21.0", - "@typescript-eslint/utils": "8.21.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/utils": "8.22.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, @@ -1671,14 +1714,14 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", - "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1689,9 +1732,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", - "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "dev": true, "license": "MIT", "engines": { @@ -1703,14 +1746,14 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", - "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1730,16 +1773,16 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz", - "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", + "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/typescript-estree": "8.21.0" + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1754,13 +1797,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", - "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -5160,6 +5203,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "license": "MIT", @@ -5803,17 +5853,18 @@ "license": "0BSD" }, "node_modules/nock": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", - "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.0.tgz", + "integrity": "sha512-3Z2ZoZoYTR/y2I+NI16+6IzfZFKBX7MrADtoBAm7v/QKqxQUhKw+Dh+847PPS1j/FDutjfIXfrh3CJF74yITWg==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.0", + "@mswjs/interceptors": "^0.37.3", "json-stringify-safe": "^5.0.1", "propagate": "^2.0.0" }, "engines": { - "node": ">= 10.13" + "node": ">= 18" } }, "node_modules/node-fetch": { @@ -6041,6 +6092,13 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, "node_modules/p-defer": { "version": "1.0.0", "dev": true, @@ -6885,6 +6943,13 @@ "bare-events": "^2.2.0" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/node_modules/@eslint/js/package.json b/node_modules/@eslint/js/package.json index 185c2eee11..1d0220dcf7 100644 --- a/node_modules/@eslint/js/package.json +++ b/node_modules/@eslint/js/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/js", - "version": "9.18.0", + "version": "9.19.0", "description": "ESLint JavaScript language implementation", "main": "./src/index.js", "types": "./types/index.d.ts", diff --git a/node_modules/@mswjs/interceptors/ClientRequest/package.json b/node_modules/@mswjs/interceptors/ClientRequest/package.json new file mode 100644 index 0000000000..4ee863900b --- /dev/null +++ b/node_modules/@mswjs/interceptors/ClientRequest/package.json @@ -0,0 +1,6 @@ +{ + "main": "../lib/node/interceptors/ClientRequest/index.js", + "module": "../lib/node/interceptors/ClientRequest/index.mjs", + "browser": null, + "types": "../lib/node/interceptors/ClientRequest/index.d.ts" +} diff --git a/node_modules/@mswjs/interceptors/LICENSE.md b/node_modules/@mswjs/interceptors/LICENSE.md new file mode 100644 index 0000000000..e5c461e5fd --- /dev/null +++ b/node_modules/@mswjs/interceptors/LICENSE.md @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2018–present Artem Zakharchenko + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@mswjs/interceptors/README.md b/node_modules/@mswjs/interceptors/README.md new file mode 100644 index 0000000000..42b0f228a8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/README.md @@ -0,0 +1,623 @@ +[![Latest version](https://img.shields.io/npm/v/@mswjs/interceptors.svg)](https://www.npmjs.com/package/@mswjs/interceptors) + +# `@mswjs/interceptors` + +Low-level network interception library. + +This library supports intercepting the following protocols: + +- HTTP (via the `http` module, `XMLHttpRequest`, or `globalThis.fetch`); +- [WebSocket](#websocket-interception) (the `WebSocket` class in Undici and in the browser). + +## Motivation + +While there are a lot of network mocking libraries, they tend to use request interception as an implementation detail, giving you a high-level API that includes request matching, timeouts, recording, and so forth. + +This library is a barebones implementation that provides as little abstraction as possible to execute arbitrary logic upon any request. It's primarily designed as an underlying component for high-level API mocking solutions such as [Mock Service Worker](https://github.com/mswjs/msw). + +### How is this library different? + +A traditional API mocking implementation in Node.js looks roughly like this: + +```js +import http from 'node:http' + +// Store the original request function. +const originalHttpRequest = http.request + +// Override the request function entirely. +http.request = function (...args) { + // Decide if the outgoing request matches a predicate. + if (predicate(args)) { + // If it does, never create a request, respond to it + // using the mocked response from this blackbox. + return coerceToResponse.bind(this, mock) + } + + // Otherwise, construct the original request + // and perform it as-is. + return originalHttpRequest(...args) +} +``` + +The core philosophy of Interceptors is to _run as much of the underlying network code as possible_. Strange for a network mocking library, isn't it? Turns out, respecting the system's integrity and executing more of the network code leads to more resilient tests and also helps to uncover bugs in the code that would otherwise go unnoticed. + +Interceptors heavily rely on _class extension_ instead of function and module overrides. By extending the native network code, it can surgically insert the interception and mocking pieces only where necessary, leaving the rest of the system intact. + +```js +class XMLHttpRequestProxy extends XMLHttpRequest { + async send() { + // Call the request listeners and see if any of them + // returns a mocked response for this request. + const mockedResponse = await waitForRequestListeners({ request }) + + // If there is a mocked response, use it. This actually + // transitions the XMLHttpRequest instance into the correct + // response state (below is a simplified illustration). + if (mockedResponse) { + // Handle the response headers. + this.request.status = mockedResponse.status + this.request.statusText = mockedResponse.statusText + this.request.responseUrl = mockedResponse.url + this.readyState = 2 + this.trigger('readystatechange') + + // Start streaming the response body. + this.trigger('loadstart') + this.readyState = 3 + this.trigger('readystatechange') + await streamResponseBody(mockedResponse) + + // Finish the response. + this.trigger('load') + this.trigger('loadend') + this.readyState = 4 + return + } + + // Otherwise, perform the original "XMLHttpRequest.prototype.send" call. + return super.send(...args) + } +} +``` + +> The request interception algorithms differ dramatically based on the request API. Interceptors acommodate for them all, bringing the intercepted requests to a common ground—the Fetch API `Request` instance. The same applies for responses, where a Fetch API `Response` instance is translated to the appropriate response format. + +This library aims to provide _full specification compliance_ with the APIs and protocols it extends. + +## What this library does + +This library extends the following native modules: + +- `http.get`/`http.request` +- `https.get`/`https.request` +- `XMLHttpRequest` +- `fetch` +- `WebSocket` + +Once extended, it intercepts and normalizes all requests to the Fetch API `Request` instances. This way, no matter the request source (`http.ClientRequest`, `XMLHttpRequest`, `window.Request`, etc), you always get a specification-compliant request instance to work with. + +You can respond to the intercepted HTTP request by constructing a Fetch API Response instance. Instead of designing custom abstractions, this library respects the Fetch API specification and takes the responsibility to coerce a single response declaration to the appropriate response formats based on the request-issuing modules (like `http.OutgoingMessage` to respond to `http.ClientRequest`, or updating `XMLHttpRequest` response-related properties). + +## What this library doesn't do + +- Does **not** provide any request matching logic; +- Does **not** handle requests by default. + +## Getting started + +```bash +npm install @mswjs/interceptors +``` + +## Interceptors + +To use this library you need to choose one or multiple interceptors to apply. There are different interceptors exported by this library to spy on respective request-issuing modules: + +- `ClientRequestInterceptor` to spy on `http.ClientRequest` (`http.get`/`http.request`); +- `XMLHttpRequestInterceptor` to spy on `XMLHttpRequest`; +- `FetchInterceptor` to spy on `fetch`. + +Use an interceptor by constructing it and attaching request/response listeners: + +```js +import { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest' + +const interceptor = new ClientRequestInterceptor() + +// Enable the interception of requests. +interceptor.apply() + +// Listen to any "http.ClientRequest" being dispatched, +// and log its method and full URL. +interceptor.on('request', ({ request, requestId }) => { + console.log(request.method, request.url) +}) + +// Listen to any responses sent to "http.ClientRequest". +// Note that this listener is read-only and cannot affect responses. +interceptor.on( + 'response', + ({ response, isMockedResponse, request, requestId }) => { + console.log('response to %s %s was:', request.method, request.url, response) + } +) +``` + +All HTTP request interceptors implement the same events: + +- `request`, emitted whenever a request has been dispatched; +- `response`, emitted whenever any request receives a response. + +### Using multiple interceptors + +You can combine multiple interceptors to capture requests from different request-issuing modules at once. + +```js +import { BatchInterceptor } from '@mswjs/interceptors' +import { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest' +import { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest' + +const interceptor = new BatchInterceptor({ + name: 'my-interceptor', + interceptors: [ + new ClientRequestInterceptor(), + new XMLHttpRequestInterceptor(), + ], +}) + +interceptor.apply() + +// This "request" listener will be called on both +// "http.ClientRequest" and "XMLHttpRequest" being dispatched. +interceptor.on('request', listener) +``` + +> Note that you can use [pre-defined presets](#presets) that cover all the request sources for a given environment type. + +## Presets + +When using [`BatchInterceptor`](#batchinterceptor), you can provide a pre-defined preset to its "interceptors" option to capture all request for that environment. + +### Node.js preset + +This preset combines `ClientRequestInterceptor`, `XMLHttpRequestInterceptor` and is meant to be used in Node.js. + +```js +import { BatchInterceptor } from '@mswjs/interceptors' +import nodeInterceptors from '@mswjs/interceptors/presets/node' + +const interceptor = new BatchInterceptor({ + name: 'my-interceptor', + interceptors: nodeInterceptors, +}) + +interceptor.apply() + +interceptor.on('request', listener) +``` + +### Browser preset + +This preset combines `XMLHttpRequestInterceptor` and `FetchInterceptor` and is meant to be used in a browser. + +```js +import { BatchInterceptor } from '@mswjs/interceptors' +import browserInterceptors from '@mswjs/interceptors/presets/browser' + +const interceptor = new BatchInterceptor({ + name: 'my-interceptor', + interceptors: browserInterceptors, +}) + +interceptor.on('request', listener) +``` + +## Introspecting requests + +All HTTP request interceptors emit a "request" event. In the listener to this event, they expose a `request` reference, which is a [Fetch API Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) instance. + +> There are many ways to describe a request in Node.js but this library coerces different request definitions to a single specification-compliant `Request` instance to make the handling consistent. + +```js +interceptor.on('request', ({ request, requestId, controller }) => { + console.log(request.method, request.url) +}) +``` + +Since the exposed `request` instance implements the Fetch API specification, you can operate with it just as you do with the regular browser request. For example, this is how you would read the request body as JSON: + +```js +interceptor.on('request', async ({ request, requestId }) => { + const json = await request.clone().json() +}) +``` + +> **Do not forget to clone the request before reading its body!** + +## Modifying requests + +Request representations are readonly. You can, however, mutate the intercepted request's headers in the "request" listener: + +```js +interceptor.on('request', ({ request }) => { + request.headers.set('X-My-Header', 'true') +}) +``` + +> This restriction is done so that the library wouldn't have to unnecessarily synchronize the actual request instance and its Fetch API request representation. As of now, this library is not meant to be used as a full-scale proxy. + +## Mocking responses + +Although this library can be used purely for request introspection purposes, you can also affect request resolution by responding to any intercepted request within the "request" event. + +Access the `controller` object from the request event listener arguments and call its `controller.respondWith()` method, providing it with a mocked `Response` instance: + +```js +interceptor.on('request', ({ request, controller }) => { + controller.respondWith( + new Response( + JSON.stringify({ + firstName: 'John', + lastName: 'Maverick', + }), + { + status: 201, + statusText: 'Created', + headers: { + 'Content-Type': 'application/json', + }, + } + ) + ) +}) +``` + +> We use Fetch API `Response` class as the middle-ground for mocked response definition. This library then coerces the response instance to the appropriate response format (e.g. to `http.OutgoingMessage` in the case of `http.ClientRequest`). + +**The `Response` class is built-in in since Node.js 18. Use a Fetch API-compatible polyfill, like `node-fetch`, for older versions of Node.js.`** + +Note that a single request _can only be handled once_. You may want to introduce conditional logic, like routing, in your request listener but it's generally advised to use a higher-level library like [Mock Service Worker](https://github.com/mswjs/msw) that does request matching for you. + +Requests must be responded to within the same tick as the request listener. This means you cannot respond to a request using `setTimeout`, as this will delegate the callback to the next tick. If you wish to introduce asynchronous side-effects in the listener, consider making it an `async` function, awaiting any side-effects you need. + +```js +// Respond to all requests with a 500 response +// delayed by 500ms. +interceptor.on('request', async ({ controller }) => { + await sleep(500) + controller.respondWith(new Response(null, { status: 500 })) +}) +``` + +### Mocking response errors + +You can provide an instance of `Response.error()` to error the pending request. + +```js +interceptor.on('request', ({ request, controller }) => { + controller.respondWith(Response.error()) +}) +``` + +This will automatically translate to the appropriate request error based on the request client that issued the request. **Use this method to produce a generic network error**. + +> Note that the standard `Response.error()` API does not accept an error message. + +## Mocking errors + +Use the `controller.errorWith()` method to error the request. + +```js +interceptor.on('request', ({ request, controller }) => { + controller.errorWith(new Error('reason')) +}) +``` + +Unlike responding with `Response.error()`, you can provide an exact error reason to use to `.errorWith()`. **Use this method to error the request**. + +> Note that it is up to the request client to respect your custom error. Some clients, like `ClientRequest` will use the provided error message, while others, like `fetch`, will produce a generic `TypeError: failed to fetch` responses. Interceptors will try to preserve the original error in the `cause` property of such generic errors. + +## Observing responses + +You can use the "response" event to transparently observe any incoming responses in your Node.js process. + +```js +interceptor.on( + 'response', + ({ response, isMockedResponse, request, requestId }) => { + // react to the incoming response... + } +) +``` + +> Note that the `isMockedResponse` property will only be set to `true` if you resolved this request in the "request" event listener using the `controller.respondWith()` method and providing a mocked `Response` instance. + +## Error handling + +By default, all unhandled exceptions thrown within the `request` listener are coerced to 500 error responses, emulating those exceptions occurring on the actual server. You can listen to the exceptions by adding the `unhandledException` listener to the interceptor: + +```js +interceptor.on( + 'unhandledException', + ({ error, request, requestId, controller }) => { + console.log(error) + } +) +``` + +To opt out from the default coercion of unhandled exceptions to server responses, you need to either: + +1. Respond to the request with [a mocked response](#mocking-responses) (including error responses); +1. Propagate the error up by throwing it explicitly in the `unhandledException` listener. + +Here's an example of propagating the unhandled exception up: + +```js +interceptor.on('unhandledException', ({ error }) => { + // Now, any unhandled exception will NOT be coerced to a 500 error response, + // and instead will be thrown during the process execution as-is. + throw error +}) +``` + +## WebSocket interception + +You can intercept a WebSocket communication using the `WebSocketInterceptor` class. + +> [!IMPORTANT] +> This library only supports intercepting WebSocket connections created using the global WHATWG `WebSocket` class. Third-party transports, such as HTTP/XHR polling, are not supported by design due to their contrived nature. + +```js +import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket' + +const interceptor = new WebSocketInterceptor() +``` + +Unlike the HTTP-based interceptors that share the same `request`/`response` events, the WebSocket interceptor only emits the `connection` event and let's you handle the incoming/outgoing events in its listener. + +### Important defaults + +1. Intercepted WebSocket connections are _not opened_. To open the actual WebSocket connection, call [`server.connect()`](#connect) in the interceptor. +1. Once connected to the actual server, the outgoing client events are _forwarded to that server by default_. If you wish to prevent a client message from reaching the server, call `event.preventDefault()` for that client message event. +1. Once connected to the actual server, the incoming server events are _forwarded to the client by default_. If you wish to prevent a server message from reaching the client, call `event.preventDefault()` for the server message event. +1. Once connected to the actual server, the `close` event received from that server is _forwarded to the client by default_. If you wish to prevent that, call `event.preventDefault()` for that close event of the server. + +### WebSocket connection + +Whenever a WebSocket instance is constructed, the `connection` event is emitted on the WebSocket interceptor. + +```js +intereceptor.on('connection', ({ client }) => { + console.log(client.url) +}) +``` + +The `connection` event exposes the following arguments: + +| Name | Type | Description | +| -------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `client` | [`WebSocketClientConnection`](#websocketclientconnection) | An object representing a connected WebSocket client instance. | +| `server` | [`WebSocketServerConnection`](#websocketserverconnection) | An object representing the original WebSocket server connection. | +| `info` | `object` | Additional WebSocket connection information (like the original client `protocols`). | + +### `WebSocketClientConnection` + +#### `.addEventListener(type, listener)` + +- `type`, `string` +- `listener`, `EventListener` + +Adds an event listener to the given event type of the WebSocket client. + +```ts +interface WebSocketServerConnectionEventMap { + // Dispatched when the WebSocket client sends data. + message: (this: WebSocket, event: MessageEvent) => void + + // Dispatched when the WebSocket client is closed. + close: (this: WebSocket, event: CloseEvent) => void +} +``` + +```js +client.addEventListener('message', (event) => { + console.log('outgoing:', event.data) +}) +``` + +#### `.removeEventListener(type, listener)` + +- `type`, `string` +- `listener`, `EventListener` + +Removes the listener for the given event type. + +#### `.send(data)` + +- `data`, `string | Blob | ArrayBuffer` + +Sends the data to the intercepted WebSocket client. + +```js +client.send('text') +client.send(new Blob(['blob'])) +client.send(new TextEncoder().encode('array buffer')) +``` + +#### `.close(code, reason)` + +- `code`, close [status code](https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1). +- `reason`, [close reason](https://www.rfc-editor.org/rfc/rfc6455#section-7.1.6). + +Closes the client connection. Unlike the regular `WebSocket.prototype.close()`, the `client.close()` method can accept a non-configurable status codes, such as 1001, 1003, etc. + +```js +// Gracefully close the connection with the +// intercepted WebSocket client. +client.close() +``` + +```js +// Terminate the connection by emulating +// the server unable to process the received data. +client.close(1003) +``` + +### `WebSocketServerConnection` + +#### `.connect()` + +Establishes the connection to the original WebSocket server. Connection cannot be awaited. Any data sent via `server.send()` while connecting is buffered and flushed once the connection is open. + +#### `.addEventListener(type, listener)` + +- `type`, `string` +- `listener`, `EventListener` + +Adds an event listener to the given event type of the WebSocket server. + +```ts +interface WebSocketServerConnectionEventMap { + // Dispatched when the server connection is open. + open: (this: WebSocket, event: Event) => void + + // Dispatched when the server sends data to the client. + message: (this: WebSocket, event: MessageEvent) => void + + // Dispatched when the server connection closes. + close: (this: WebSocket, event: CloseEvent) => void +} +``` + +```js +server.addEventListener('message', (event) => { + console.log('incoming:', event.data) +}) +``` + +#### `.removeEventListener(type, listener)` + +- `type`, `string` +- `listener`, `EventListener` + +Removes the listener for the given event type. + +#### `.send(data)` + +- `data`, `string | Blob | ArrayBuffer` + +Sends the data to the original WebSocket server. Useful in a combination with the client-sent events forwarding: + +```js +client.addEventListener('message', (event) => { + server.send(event.data) +}) +``` + +#### `.close()` + +Closes the connection with the original WebSocket server. Unlike `client.close()`, closing the server connection does not accept any arguments and always asumes a graceful closure. Sending data via `server.send()` after the connection has been closed will have no effect. + +## API + +### `Interceptor` + +A generic class implemented by all interceptors. You do not interact with this class directly. + +```ts +class Interceptor { + // Applies the interceptor, enabling the interception of requests + // in the current process. + apply(): void + + // Listens to the public interceptor events. + // For HTTP requests, these are "request' and "response" events. + on(event, listener): void + + // Cleans up any side-effects introduced by the interceptor + // and disables the interception of requests. + dispose(): void +} +``` + +**For public consumption, use [interceptors](#interceptors) instead**. + +### `BatchInterceptor` + +Applies multiple request interceptors at the same time. + +```js +import { BatchInterceptor } from '@mswjs/interceptors' +import nodeInterceptors from '@mswjs/interceptors/presets/node' + +const interceptor = new BatchInterceptor({ + name: 'my-interceptor', + interceptors: nodeInterceptors, +}) + +interceptor.apply() + +interceptor.on('request', ({ request, requestId }) => { + // Inspect the intercepted "request". + // Optionally, return a mocked response. +}) +``` + +> Using the `/presets/node` interceptors preset is the recommended way to ensure all requests get intercepted, regardless of their origin. + +### `RemoteHttpInterceptor` + +Enables request interception in the current process while delegating the response resolution logic to the _parent process_. **Requires the current process to be a child process**. Requires the parent process to establish a resolver by calling the `createRemoteResolver` function. + +```js +// child.js +import { RemoteHttpInterceptor } from '@mswjs/interceptors/RemoteHttpInterceptor' +import { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest' + +const interceptor = new RemoteHttpInterceptor({ + // Alternatively, you can use presets. + interceptors: [new ClientRequestInterceptor()], +}) + +interceptor.apply() + +process.on('disconnect', () => { + interceptor.dispose() +}) +``` + +You can still listen to and handle any requests in the child process via the `request` event listener. Keep in mind that a single request can only be responded to once. + +### `RemoteHttpResolver` + +Resolves an intercepted request in the given child `process`. Requires for that child process to enable request interception by calling the `createRemoteInterceptor` function. + +```js +// parent.js +import { spawn } from 'child_process' +import { RemoteHttpResolver } from '@mswjs/interceptors/RemoteHttpInterceptor' + +const appProcess = spawn('node', ['app.js'], { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'], +}) + +const resolver = new RemoteHttpResolver({ + process: appProcess, +}) + +resolver.on('request', ({ request, requestId }) => { + // Optionally, return a mocked response + // for a request that occurred in the "appProcess". +}) + +resolver.apply() +``` + +## Special mention + +The following libraries were used as an inspiration to write this low-level API: + +- [`node`](https://github.com/nodejs/node) +- [`nock`](https://github.com/nock/nock) +- [`mock-xmlhttprequest`](https://github.com/berniegp/mock-xmlhttprequest) diff --git a/node_modules/@mswjs/interceptors/RemoteHttpInterceptor/package.json b/node_modules/@mswjs/interceptors/RemoteHttpInterceptor/package.json new file mode 100644 index 0000000000..bc5d53aaff --- /dev/null +++ b/node_modules/@mswjs/interceptors/RemoteHttpInterceptor/package.json @@ -0,0 +1,6 @@ +{ + "main": "../lib/node/RemoteHttpInterceptor.js", + "module": "../lib/node/RemoteHttpInterceptor.mjs", + "browser": null, + "types": "../lib/node/RemoteHttpInterceptor.d.ts" +} diff --git a/node_modules/@mswjs/interceptors/WebSocket/package.json b/node_modules/@mswjs/interceptors/WebSocket/package.json new file mode 100644 index 0000000000..52dfef27bd --- /dev/null +++ b/node_modules/@mswjs/interceptors/WebSocket/package.json @@ -0,0 +1,5 @@ +{ + "main": "../lib/browser/interceptors/WebSocket/index.js", + "module": "../lib/browser/interceptors/WebSocket/index.mjs", + "types": "../lib/browser/interceptors/WebSocket/index.d.ts" +} diff --git a/node_modules/@mswjs/interceptors/XMLHttpRequest/package.json b/node_modules/@mswjs/interceptors/XMLHttpRequest/package.json new file mode 100644 index 0000000000..8830bae0e2 --- /dev/null +++ b/node_modules/@mswjs/interceptors/XMLHttpRequest/package.json @@ -0,0 +1,6 @@ +{ + "main": "../lib/node/interceptors/XMLHttpRequest/index.js", + "module": "../lib/node/interceptors/XMLHttpRequest/index.mjs", + "browser": "../lib/browser/interceptors/XMLHttpRequest/index.js", + "types": "../lib/node/interceptors/XMLHttpRequest/index.d.ts" +} diff --git a/node_modules/@mswjs/interceptors/fetch/package.json b/node_modules/@mswjs/interceptors/fetch/package.json new file mode 100644 index 0000000000..5e5dac8573 --- /dev/null +++ b/node_modules/@mswjs/interceptors/fetch/package.json @@ -0,0 +1,6 @@ +{ + "main": "../lib/node/interceptors/fetch/index.js", + "module": "../lib/node/interceptors/fetch/index.mjs", + "browser": "../lib/browser/interceptors/fetch/index.js", + "types": "../lib/node/interceptors/fetch/index.d.ts" +} diff --git a/node_modules/@mswjs/interceptors/lib/browser/Interceptor-af98b768.d.ts b/node_modules/@mswjs/interceptors/lib/browser/Interceptor-af98b768.d.ts new file mode 100644 index 0000000000..257c42dde0 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/Interceptor-af98b768.d.ts @@ -0,0 +1,63 @@ +import { Logger } from '@open-draft/logger'; +import { Emitter, Listener } from 'strict-event-emitter'; + +type InterceptorEventMap = Record; +type InterceptorSubscription = () => void; +/** + * Request header name to detect when a single request + * is being handled by nested interceptors (XHR -> ClientRequest). + * Obscure by design to prevent collisions with user-defined headers. + * Ideally, come up with the Interceptor-level mechanism for this. + * @see https://github.com/mswjs/interceptors/issues/378 + */ +declare const INTERNAL_REQUEST_ID_HEADER_NAME = "x-interceptors-internal-request-id"; +declare function getGlobalSymbol(symbol: Symbol): V | undefined; +declare function deleteGlobalSymbol(symbol: Symbol): void; +declare enum InterceptorReadyState { + INACTIVE = "INACTIVE", + APPLYING = "APPLYING", + APPLIED = "APPLIED", + DISPOSING = "DISPOSING", + DISPOSED = "DISPOSED" +} +type ExtractEventNames> = Events extends Record ? EventName : never; +declare class Interceptor { + private readonly symbol; + protected emitter: Emitter; + protected subscriptions: Array; + protected logger: Logger; + readyState: InterceptorReadyState; + constructor(symbol: symbol); + /** + * Determine if this interceptor can be applied + * in the current environment. + */ + protected checkEnvironment(): boolean; + /** + * Apply this interceptor to the current process. + * Returns an already running interceptor instance if it's present. + */ + apply(): void; + /** + * Setup the module augments and stubs necessary for this interceptor. + * This method is not run if there's a running interceptor instance + * to prevent instantiating an interceptor multiple times. + */ + protected setup(): void; + /** + * Listen to the interceptor's public events. + */ + on>(event: EventName, listener: Listener): this; + once>(event: EventName, listener: Listener): this; + off>(event: EventName, listener: Listener): this; + removeAllListeners>(event?: EventName): this; + /** + * Disposes of any side-effects this interceptor has introduced. + */ + dispose(): void; + private getInstance; + private setInstance; + private clearInstance; +} + +export { ExtractEventNames as E, Interceptor as I, InterceptorEventMap as a, InterceptorSubscription as b, INTERNAL_REQUEST_ID_HEADER_NAME as c, deleteGlobalSymbol as d, InterceptorReadyState as e, getGlobalSymbol as g }; diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-5UK33FSU.mjs b/node_modules/@mswjs/interceptors/lib/browser/chunk-5UK33FSU.mjs new file mode 100644 index 0000000000..73f3289ca9 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-5UK33FSU.mjs @@ -0,0 +1,83 @@ +// src/glossary.ts +var IS_PATCHED_MODULE = Symbol("isPatchedModule"); + +// src/utils/fetchUtils.ts +var _FetchResponse = class extends Response { + static isConfigurableStatusCode(status) { + return status >= 200 && status <= 599; + } + static isRedirectResponse(status) { + return _FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status); + } + /** + * Returns a boolean indicating whether the given response status + * code represents a response that can have a body. + */ + static isResponseWithBody(status) { + return !_FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status); + } + static setUrl(url, response) { + if (!url) { + return; + } + if (response.url != "") { + return; + } + Object.defineProperty(response, "url", { + value: url, + enumerable: true, + configurable: true, + writable: false + }); + } + /** + * Parses the given raw HTTP headers into a Fetch API `Headers` instance. + */ + static parseRawHeaders(rawHeaders) { + const headers = new Headers(); + for (let line = 0; line < rawHeaders.length; line += 2) { + headers.append(rawHeaders[line], rawHeaders[line + 1]); + } + return headers; + } + constructor(body, init = {}) { + var _a; + const status = (_a = init.status) != null ? _a : 200; + const safeStatus = _FetchResponse.isConfigurableStatusCode(status) ? status : 200; + const finalBody = _FetchResponse.isResponseWithBody(status) ? body : null; + super(finalBody, { + ...init, + status: safeStatus + }); + if (status !== safeStatus) { + const stateSymbol = Object.getOwnPropertySymbols(this).find( + (symbol) => symbol.description === "state" + ); + if (stateSymbol) { + const state = Reflect.get(this, stateSymbol); + Reflect.set(state, "status", status); + } else { + Object.defineProperty(this, "status", { + value: status, + enumerable: true, + configurable: true, + writable: false + }); + } + } + _FetchResponse.setUrl(init.url, this); + } +}; +var FetchResponse = _FetchResponse; +/** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ +FetchResponse.STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]; +FetchResponse.STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]; + +export { + IS_PATCHED_MODULE, + FetchResponse +}; +//# sourceMappingURL=chunk-5UK33FSU.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-5UK33FSU.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-5UK33FSU.mjs.map new file mode 100644 index 0000000000..df0c20792c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-5UK33FSU.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/glossary.ts","../../src/utils/fetchUtils.ts"],"sourcesContent":["import type { RequestController } from './RequestController'\n\nexport const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')\n\n/**\n * @note Export `RequestController` as a type only.\n * It's never meant to be created in the userland.\n */\nexport type { RequestController }\n\nexport type RequestCredentials = 'omit' | 'include' | 'same-origin'\n\nexport type HttpRequestEventMap = {\n request: [\n args: {\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n response: [\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ]\n unhandledException: [\n args: {\n error: unknown\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n}\n","export interface FetchResponseInit extends ResponseInit {\n url?: string\n}\n\nexport class FetchResponse extends Response {\n /**\n * Response status codes for responses that cannot have body.\n * @see https://fetch.spec.whatwg.org/#statuses\n */\n static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n static isConfigurableStatusCode(status: number): boolean {\n return status >= 200 && status <= 599\n }\n\n static isRedirectResponse(status: number): boolean {\n return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n }\n\n /**\n * Returns a boolean indicating whether the given response status\n * code represents a response that can have a body.\n */\n static isResponseWithBody(status: number): boolean {\n return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n }\n\n static setUrl(url: string | undefined, response: Response): void {\n if (!url) {\n return\n }\n\n if (response.url != '') {\n return\n }\n\n Object.defineProperty(response, 'url', {\n value: url,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n /**\n * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n */\n static parseRawHeaders(rawHeaders: Array): Headers {\n const headers = new Headers()\n for (let line = 0; line < rawHeaders.length; line += 2) {\n headers.append(rawHeaders[line], rawHeaders[line + 1])\n }\n return headers\n }\n\n constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n const status = init.status ?? 200\n const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n ? status\n : 200\n const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n super(finalBody, {\n ...init,\n status: safeStatus,\n })\n\n if (status !== safeStatus) {\n /**\n * @note Undici keeps an internal \"Symbol(state)\" that holds\n * the actual value of response status. Update that in Node.js.\n */\n const stateSymbol = Object.getOwnPropertySymbols(this).find(\n (symbol) => symbol.description === 'state'\n )\n if (stateSymbol) {\n const state = Reflect.get(this, stateSymbol) as object\n Reflect.set(state, 'status', status)\n } else {\n Object.defineProperty(this, 'status', {\n value: status,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n\n FetchResponse.setUrl(init.url, this)\n }\n}\n"],"mappings":";AAEO,IAAM,oBAAmC,OAAO,iBAAiB;;;ACEjE,IAAM,iBAAN,cAA4B,SAAS;AAAA,EAS1C,OAAO,yBAAyB,QAAyB;AACvD,WAAO,UAAU,OAAO,UAAU;AAAA,EACpC;AAAA,EAEA,OAAO,mBAAmB,QAAyB;AACjD,WAAO,eAAc,2BAA2B,SAAS,MAAM;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,QAAyB;AACjD,WAAO,CAAC,eAAc,0BAA0B,SAAS,MAAM;AAAA,EACjE;AAAA,EAEA,OAAO,OAAO,KAAyB,UAA0B;AAC/D,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,IAAI;AACtB;AAAA,IACF;AAEA,WAAO,eAAe,UAAU,OAAO;AAAA,MACrC,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,gBAAgB,YAAoC;AACzD,UAAM,UAAU,IAAI,QAAQ;AAC5B,aAAS,OAAO,GAAG,OAAO,WAAW,QAAQ,QAAQ,GAAG;AACtD,cAAQ,OAAO,WAAW,IAAI,GAAG,WAAW,OAAO,CAAC,CAAC;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,MAAwB,OAA0B,CAAC,GAAG;AAzDpE;AA0DI,UAAM,UAAS,UAAK,WAAL,YAAe;AAC9B,UAAM,aAAa,eAAc,yBAAyB,MAAM,IAC5D,SACA;AACJ,UAAM,YAAY,eAAc,mBAAmB,MAAM,IAAI,OAAO;AAEpE,UAAM,WAAW;AAAA,MACf,GAAG;AAAA,MACH,QAAQ;AAAA,IACV,CAAC;AAED,QAAI,WAAW,YAAY;AAKzB,YAAM,cAAc,OAAO,sBAAsB,IAAI,EAAE;AAAA,QACrD,CAAC,WAAW,OAAO,gBAAgB;AAAA,MACrC;AACA,UAAI,aAAa;AACf,cAAM,QAAQ,QAAQ,IAAI,MAAM,WAAW;AAC3C,gBAAQ,IAAI,OAAO,UAAU,MAAM;AAAA,MACrC,OAAO;AACL,eAAO,eAAe,MAAM,UAAU;AAAA,UACpC,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,cAAc;AAAA,UACd,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,mBAAc,OAAO,KAAK,KAAK,IAAI;AAAA,EACrC;AACF;AAxFO,IAAM,gBAAN;AAAA;AAAA;AAAA;AAAA;AAAM,cAKK,4BAA4B,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AALzD,cAOK,6BAA6B,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs b/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs new file mode 100644 index 0000000000..05b6c33cb2 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs @@ -0,0 +1,22 @@ +// src/utils/bufferUtils.ts +var encoder = new TextEncoder(); +function encodeBuffer(text) { + return encoder.encode(text); +} +function decodeBuffer(buffer, encoding) { + const decoder = new TextDecoder(encoding); + return decoder.decode(buffer); +} +function toArrayBuffer(array) { + return array.buffer.slice( + array.byteOffset, + array.byteOffset + array.byteLength + ); +} + +export { + encodeBuffer, + decodeBuffer, + toArrayBuffer +}; +//# sourceMappingURL=chunk-6HYIRFX2.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs.map new file mode 100644 index 0000000000..6f27915c41 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-6HYIRFX2.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/bufferUtils.ts"],"sourcesContent":["const encoder = new TextEncoder()\n\nexport function encodeBuffer(text: string): Uint8Array {\n return encoder.encode(text)\n}\n\nexport function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string {\n const decoder = new TextDecoder(encoding)\n return decoder.decode(buffer)\n}\n\n/**\n * Create an `ArrayBuffer` from the given `Uint8Array`.\n * Takes the byte offset into account to produce the right buffer\n * in the case when the buffer is bigger than the data view.\n */\nexport function toArrayBuffer(array: Uint8Array): ArrayBuffer {\n return array.buffer.slice(\n array.byteOffset,\n array.byteOffset + array.byteLength\n )\n}\n"],"mappings":";AAAA,IAAM,UAAU,IAAI,YAAY;AAEzB,SAAS,aAAa,MAA0B;AACrD,SAAO,QAAQ,OAAO,IAAI;AAC5B;AAEO,SAAS,aAAa,QAAqB,UAA2B;AAC3E,QAAM,UAAU,IAAI,YAAY,QAAQ;AACxC,SAAO,QAAQ,OAAO,MAAM;AAC9B;AAOO,SAAS,cAAc,OAAgC;AAC5D,SAAO,MAAM,OAAO;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,aAAa,MAAM;AAAA,EAC3B;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-BC2BLJQN.js b/node_modules/@mswjs/interceptors/lib/browser/chunk-BC2BLJQN.js new file mode 100644 index 0000000000..dfa8d168b7 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-BC2BLJQN.js @@ -0,0 +1,83 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/glossary.ts +var IS_PATCHED_MODULE = Symbol("isPatchedModule"); + +// src/utils/fetchUtils.ts +var _FetchResponse = class extends Response { + static isConfigurableStatusCode(status) { + return status >= 200 && status <= 599; + } + static isRedirectResponse(status) { + return _FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status); + } + /** + * Returns a boolean indicating whether the given response status + * code represents a response that can have a body. + */ + static isResponseWithBody(status) { + return !_FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status); + } + static setUrl(url, response) { + if (!url) { + return; + } + if (response.url != "") { + return; + } + Object.defineProperty(response, "url", { + value: url, + enumerable: true, + configurable: true, + writable: false + }); + } + /** + * Parses the given raw HTTP headers into a Fetch API `Headers` instance. + */ + static parseRawHeaders(rawHeaders) { + const headers = new Headers(); + for (let line = 0; line < rawHeaders.length; line += 2) { + headers.append(rawHeaders[line], rawHeaders[line + 1]); + } + return headers; + } + constructor(body, init = {}) { + var _a; + const status = (_a = init.status) != null ? _a : 200; + const safeStatus = _FetchResponse.isConfigurableStatusCode(status) ? status : 200; + const finalBody = _FetchResponse.isResponseWithBody(status) ? body : null; + super(finalBody, { + ...init, + status: safeStatus + }); + if (status !== safeStatus) { + const stateSymbol = Object.getOwnPropertySymbols(this).find( + (symbol) => symbol.description === "state" + ); + if (stateSymbol) { + const state = Reflect.get(this, stateSymbol); + Reflect.set(state, "status", status); + } else { + Object.defineProperty(this, "status", { + value: status, + enumerable: true, + configurable: true, + writable: false + }); + } + } + _FetchResponse.setUrl(init.url, this); + } +}; +var FetchResponse = _FetchResponse; +/** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ +FetchResponse.STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]; +FetchResponse.STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]; + + + + +exports.IS_PATCHED_MODULE = IS_PATCHED_MODULE; exports.FetchResponse = FetchResponse; +//# sourceMappingURL=chunk-BC2BLJQN.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-BC2BLJQN.js.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-BC2BLJQN.js.map new file mode 100644 index 0000000000..5fbb9c76b8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-BC2BLJQN.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/glossary.ts","../../src/utils/fetchUtils.ts"],"names":[],"mappings":";AAEO,IAAM,oBAAmC,OAAO,iBAAiB;;;ACEjE,IAAM,iBAAN,cAA4B,SAAS;AAAA,EAS1C,OAAO,yBAAyB,QAAyB;AACvD,WAAO,UAAU,OAAO,UAAU;AAAA,EACpC;AAAA,EAEA,OAAO,mBAAmB,QAAyB;AACjD,WAAO,eAAc,2BAA2B,SAAS,MAAM;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,QAAyB;AACjD,WAAO,CAAC,eAAc,0BAA0B,SAAS,MAAM;AAAA,EACjE;AAAA,EAEA,OAAO,OAAO,KAAyB,UAA0B;AAC/D,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,IAAI;AACtB;AAAA,IACF;AAEA,WAAO,eAAe,UAAU,OAAO;AAAA,MACrC,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,gBAAgB,YAAoC;AACzD,UAAM,UAAU,IAAI,QAAQ;AAC5B,aAAS,OAAO,GAAG,OAAO,WAAW,QAAQ,QAAQ,GAAG;AACtD,cAAQ,OAAO,WAAW,IAAI,GAAG,WAAW,OAAO,CAAC,CAAC;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,MAAwB,OAA0B,CAAC,GAAG;AAzDpE;AA0DI,UAAM,UAAS,UAAK,WAAL,YAAe;AAC9B,UAAM,aAAa,eAAc,yBAAyB,MAAM,IAC5D,SACA;AACJ,UAAM,YAAY,eAAc,mBAAmB,MAAM,IAAI,OAAO;AAEpE,UAAM,WAAW;AAAA,MACf,GAAG;AAAA,MACH,QAAQ;AAAA,IACV,CAAC;AAED,QAAI,WAAW,YAAY;AAKzB,YAAM,cAAc,OAAO,sBAAsB,IAAI,EAAE;AAAA,QACrD,CAAC,WAAW,OAAO,gBAAgB;AAAA,MACrC;AACA,UAAI,aAAa;AACf,cAAM,QAAQ,QAAQ,IAAI,MAAM,WAAW;AAC3C,gBAAQ,IAAI,OAAO,UAAU,MAAM;AAAA,MACrC,OAAO;AACL,eAAO,eAAe,MAAM,UAAU;AAAA,UACpC,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,cAAc;AAAA,UACd,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,mBAAc,OAAO,KAAK,KAAK,IAAI;AAAA,EACrC;AACF;AAxFO,IAAM,gBAAN;AAAA;AAAA;AAAA;AAAA;AAAM,cAKK,4BAA4B,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG;AALzD,cAOK,6BAA6B,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG","sourcesContent":["import type { RequestController } from './RequestController'\n\nexport const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')\n\n/**\n * @note Export `RequestController` as a type only.\n * It's never meant to be created in the userland.\n */\nexport type { RequestController }\n\nexport type RequestCredentials = 'omit' | 'include' | 'same-origin'\n\nexport type HttpRequestEventMap = {\n request: [\n args: {\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n response: [\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ]\n unhandledException: [\n args: {\n error: unknown\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n}\n","export interface FetchResponseInit extends ResponseInit {\n url?: string\n}\n\nexport class FetchResponse extends Response {\n /**\n * Response status codes for responses that cannot have body.\n * @see https://fetch.spec.whatwg.org/#statuses\n */\n static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n static isConfigurableStatusCode(status: number): boolean {\n return status >= 200 && status <= 599\n }\n\n static isRedirectResponse(status: number): boolean {\n return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n }\n\n /**\n * Returns a boolean indicating whether the given response status\n * code represents a response that can have a body.\n */\n static isResponseWithBody(status: number): boolean {\n return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n }\n\n static setUrl(url: string | undefined, response: Response): void {\n if (!url) {\n return\n }\n\n if (response.url != '') {\n return\n }\n\n Object.defineProperty(response, 'url', {\n value: url,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n /**\n * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n */\n static parseRawHeaders(rawHeaders: Array): Headers {\n const headers = new Headers()\n for (let line = 0; line < rawHeaders.length; line += 2) {\n headers.append(rawHeaders[line], rawHeaders[line + 1])\n }\n return headers\n }\n\n constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n const status = init.status ?? 200\n const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n ? status\n : 200\n const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n super(finalBody, {\n ...init,\n status: safeStatus,\n })\n\n if (status !== safeStatus) {\n /**\n * @note Undici keeps an internal \"Symbol(state)\" that holds\n * the actual value of response status. Update that in Node.js.\n */\n const stateSymbol = Object.getOwnPropertySymbols(this).find(\n (symbol) => symbol.description === 'state'\n )\n if (stateSymbol) {\n const state = Reflect.get(this, stateSymbol) as object\n Reflect.set(state, 'status', status)\n } else {\n Object.defineProperty(this, 'status', {\n value: status,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n\n FetchResponse.setUrl(init.url, this)\n }\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-DODHRDV6.mjs b/node_modules/@mswjs/interceptors/lib/browser/chunk-DODHRDV6.mjs new file mode 100644 index 0000000000..42d1cced71 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-DODHRDV6.mjs @@ -0,0 +1,844 @@ +import { + decodeBuffer, + encodeBuffer, + toArrayBuffer +} from "./chunk-6HYIRFX2.mjs"; +import { + RequestController, + handleRequest +} from "./chunk-H5O73WD2.mjs"; +import { + FetchResponse, + IS_PATCHED_MODULE +} from "./chunk-5UK33FSU.mjs"; +import { + hasConfigurableGlobal +} from "./chunk-TX5GBTFY.mjs"; +import { + INTERNAL_REQUEST_ID_HEADER_NAME, + Interceptor, + createRequestId +} from "./chunk-QED3Q6Z2.mjs"; + +// src/interceptors/XMLHttpRequest/index.ts +import { invariant as invariant2 } from "outvariant"; + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +import { invariant } from "outvariant"; +import { isNodeProcess } from "is-node-process"; + +// src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +function concatArrayBuffer(left, right) { + const result = new Uint8Array(left.byteLength + right.byteLength); + result.set(left, 0); + result.set(right, left.byteLength); + return result; +} + +// src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +var EventPolyfill = class { + constructor(type, options) { + this.NONE = 0; + this.CAPTURING_PHASE = 1; + this.AT_TARGET = 2; + this.BUBBLING_PHASE = 3; + this.type = ""; + this.srcElement = null; + this.currentTarget = null; + this.eventPhase = 0; + this.isTrusted = true; + this.composed = false; + this.cancelable = true; + this.defaultPrevented = false; + this.bubbles = true; + this.lengthComputable = true; + this.loaded = 0; + this.total = 0; + this.cancelBubble = false; + this.returnValue = true; + this.type = type; + this.target = (options == null ? void 0 : options.target) || null; + this.currentTarget = (options == null ? void 0 : options.currentTarget) || null; + this.timeStamp = Date.now(); + } + composedPath() { + return []; + } + initEvent(type, bubbles, cancelable) { + this.type = type; + this.bubbles = !!bubbles; + this.cancelable = !!cancelable; + } + preventDefault() { + this.defaultPrevented = true; + } + stopPropagation() { + } + stopImmediatePropagation() { + } +}; + +// src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +var ProgressEventPolyfill = class extends EventPolyfill { + constructor(type, init) { + super(type); + this.lengthComputable = (init == null ? void 0 : init.lengthComputable) || false; + this.composed = (init == null ? void 0 : init.composed) || false; + this.loaded = (init == null ? void 0 : init.loaded) || 0; + this.total = (init == null ? void 0 : init.total) || 0; + } +}; + +// src/interceptors/XMLHttpRequest/utils/createEvent.ts +var SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== "undefined"; +function createEvent(target, type, init) { + const progressEvents = [ + "error", + "progress", + "loadstart", + "loadend", + "load", + "timeout", + "abort" + ]; + const ProgressEventClass = SUPPORTS_PROGRESS_EVENT ? ProgressEvent : ProgressEventPolyfill; + const event = progressEvents.includes(type) ? new ProgressEventClass(type, { + lengthComputable: true, + loaded: (init == null ? void 0 : init.loaded) || 0, + total: (init == null ? void 0 : init.total) || 0 + }) : new EventPolyfill(type, { + target, + currentTarget: target + }); + return event; +} + +// src/utils/findPropertySource.ts +function findPropertySource(target, propertyName) { + if (!(propertyName in target)) { + return null; + } + const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName); + if (hasProperty) { + return target; + } + const prototype = Reflect.getPrototypeOf(target); + return prototype ? findPropertySource(prototype, propertyName) : null; +} + +// src/utils/createProxy.ts +function createProxy(target, options) { + const proxy = new Proxy(target, optionsToProxyHandler(options)); + return proxy; +} +function optionsToProxyHandler(options) { + const { constructorCall, methodCall, getProperty, setProperty } = options; + const handler = {}; + if (typeof constructorCall !== "undefined") { + handler.construct = function(target, args, newTarget) { + const next = Reflect.construct.bind(null, target, args, newTarget); + return constructorCall.call(newTarget, args, next); + }; + } + handler.set = function(target, propertyName, nextValue) { + const next = () => { + const propertySource = findPropertySource(target, propertyName) || target; + const ownDescriptors = Reflect.getOwnPropertyDescriptor( + propertySource, + propertyName + ); + if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") { + ownDescriptors.set.apply(target, [nextValue]); + return true; + } + return Reflect.defineProperty(propertySource, propertyName, { + writable: true, + enumerable: true, + configurable: true, + value: nextValue + }); + }; + if (typeof setProperty !== "undefined") { + return setProperty.call(target, [propertyName, nextValue], next); + } + return next(); + }; + handler.get = function(target, propertyName, receiver) { + const next = () => target[propertyName]; + const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next(); + if (typeof value === "function") { + return (...args) => { + const next2 = value.bind(target, ...args); + if (typeof methodCall !== "undefined") { + return methodCall.call(target, [propertyName, args], next2); + } + return next2(); + }; + } + return value; + }; + return handler; +} + +// src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +function isDomParserSupportedType(type) { + const supportedTypes = [ + "application/xhtml+xml", + "application/xml", + "image/svg+xml", + "text/html", + "text/xml" + ]; + return supportedTypes.some((supportedType) => { + return type.startsWith(supportedType); + }); +} + +// src/utils/parseJson.ts +function parseJson(data) { + try { + const json = JSON.parse(data); + return json; + } catch (_) { + return null; + } +} + +// src/interceptors/XMLHttpRequest/utils/createResponse.ts +function createResponse(request, body) { + const responseBodyOrNull = FetchResponse.isResponseWithBody(request.status) ? body : null; + return new FetchResponse(responseBodyOrNull, { + url: request.responseURL, + status: request.status, + statusText: request.statusText, + headers: createHeadersFromXMLHttpReqestHeaders( + request.getAllResponseHeaders() + ) + }); +} +function createHeadersFromXMLHttpReqestHeaders(headersString) { + const headers = new Headers(); + const lines = headersString.split(/[\r\n]+/); + for (const line of lines) { + if (line.trim() === "") { + continue; + } + const [name, ...parts] = line.split(": "); + const value = parts.join(": "); + headers.append(name, value); + } + return headers; +} + +// src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +async function getBodyByteLength(input) { + const explicitContentLength = input.headers.get("content-length"); + if (explicitContentLength != null && explicitContentLength !== "") { + return Number(explicitContentLength); + } + const buffer = await input.arrayBuffer(); + return buffer.byteLength; +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +var kIsRequestHandled = Symbol("kIsRequestHandled"); +var IS_NODE = isNodeProcess(); +var kFetchRequest = Symbol("kFetchRequest"); +var XMLHttpRequestController = class { + constructor(initialRequest, logger) { + this.initialRequest = initialRequest; + this.logger = logger; + this.method = "GET"; + this.url = null; + this[kIsRequestHandled] = false; + this.events = /* @__PURE__ */ new Map(); + this.uploadEvents = /* @__PURE__ */ new Map(); + this.requestId = createRequestId(); + this.requestHeaders = new Headers(); + this.responseBuffer = new Uint8Array(); + this.request = createProxy(initialRequest, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "ontimeout": { + const eventName = propertyName.slice( + 2 + ); + this.request.addEventListener(eventName, nextValue); + return invoke(); + } + default: { + return invoke(); + } + } + }, + methodCall: ([methodName, args], invoke) => { + var _a; + switch (methodName) { + case "open": { + const [method, url] = args; + if (typeof url === "undefined") { + this.method = "GET"; + this.url = toAbsoluteUrl(method); + } else { + this.method = method; + this.url = toAbsoluteUrl(url); + } + this.logger = this.logger.extend(`${this.method} ${this.url.href}`); + this.logger.info("open", this.method, this.url.href); + return invoke(); + } + case "addEventListener": { + const [eventName, listener] = args; + this.registerEvent(eventName, listener); + this.logger.info("addEventListener", eventName, listener); + return invoke(); + } + case "setRequestHeader": { + const [name, value] = args; + this.requestHeaders.set(name, value); + this.logger.info("setRequestHeader", name, value); + return invoke(); + } + case "send": { + const [body] = args; + this.request.addEventListener("load", () => { + if (typeof this.onResponse !== "undefined") { + const fetchResponse = createResponse( + this.request, + /** + * The `response` property is the right way to read + * the ambiguous response body, as the request's "responseType" may differ. + * @see https://xhr.spec.whatwg.org/#the-response-attribute + */ + this.request.response + ); + this.onResponse.call(this, { + response: fetchResponse, + isMockedResponse: this[kIsRequestHandled], + request: fetchRequest, + requestId: this.requestId + }); + } + }); + const requestBody = typeof body === "string" ? encodeBuffer(body) : body; + const fetchRequest = this.toFetchApiRequest(requestBody); + this[kFetchRequest] = fetchRequest.clone(); + const onceRequestSettled = ((_a = this.onRequest) == null ? void 0 : _a.call(this, { + request: fetchRequest, + requestId: this.requestId + })) || Promise.resolve(); + onceRequestSettled.finally(() => { + if (!this[kIsRequestHandled]) { + this.logger.info( + "request callback settled but request has not been handled (readystate %d), performing as-is...", + this.request.readyState + ); + if (IS_NODE) { + this.request.setRequestHeader( + INTERNAL_REQUEST_ID_HEADER_NAME, + this.requestId + ); + } + return invoke(); + } + }); + break; + } + default: { + return invoke(); + } + } + } + }); + define( + this.request, + "upload", + createProxy(this.request.upload, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "onloadstart": + case "onprogress": + case "onaboart": + case "onerror": + case "onload": + case "ontimeout": + case "onloadend": { + const eventName = propertyName.slice( + 2 + ); + this.registerUploadEvent(eventName, nextValue); + } + } + return invoke(); + }, + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "addEventListener": { + const [eventName, listener] = args; + this.registerUploadEvent(eventName, listener); + this.logger.info("upload.addEventListener", eventName, listener); + return invoke(); + } + } + } + }) + ); + } + registerEvent(eventName, listener) { + const prevEvents = this.events.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.events.set(eventName, nextEvents); + this.logger.info('registered event "%s"', eventName, listener); + } + registerUploadEvent(eventName, listener) { + const prevEvents = this.uploadEvents.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.uploadEvents.set(eventName, nextEvents); + this.logger.info('registered upload event "%s"', eventName, listener); + } + /** + * Responds to the current request with the given + * Fetch API `Response` instance. + */ + async respondWith(response) { + this[kIsRequestHandled] = true; + if (this[kFetchRequest]) { + const totalRequestBodyLength = await getBodyByteLength( + this[kFetchRequest] + ); + this.trigger("loadstart", this.request.upload, { + loaded: 0, + total: totalRequestBodyLength + }); + this.trigger("progress", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("load", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("loadend", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + } + this.logger.info( + "responding with a mocked response: %d %s", + response.status, + response.statusText + ); + define(this.request, "status", response.status); + define(this.request, "statusText", response.statusText); + define(this.request, "responseURL", this.url.href); + this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, { + apply: (_, __, args) => { + this.logger.info("getResponseHeader", args[0]); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning null"); + return null; + } + const headerValue = response.headers.get(args[0]); + this.logger.info( + 'resolved response header "%s" to', + args[0], + headerValue + ); + return headerValue; + } + }); + this.request.getAllResponseHeaders = new Proxy( + this.request.getAllResponseHeaders, + { + apply: () => { + this.logger.info("getAllResponseHeaders"); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning empty string"); + return ""; + } + const headersList = Array.from(response.headers.entries()); + const allHeaders = headersList.map(([headerName, headerValue]) => { + return `${headerName}: ${headerValue}`; + }).join("\r\n"); + this.logger.info("resolved all response headers to", allHeaders); + return allHeaders; + } + } + ); + Object.defineProperties(this.request, { + response: { + enumerable: true, + configurable: false, + get: () => this.response + }, + responseText: { + enumerable: true, + configurable: false, + get: () => this.responseText + }, + responseXML: { + enumerable: true, + configurable: false, + get: () => this.responseXML + } + }); + const totalResponseBodyLength = await getBodyByteLength(response.clone()); + this.logger.info("calculated response body length", totalResponseBodyLength); + this.trigger("loadstart", this.request, { + loaded: 0, + total: totalResponseBodyLength + }); + this.setReadyState(this.request.HEADERS_RECEIVED); + this.setReadyState(this.request.LOADING); + const finalizeResponse = () => { + this.logger.info("finalizing the mocked response..."); + this.setReadyState(this.request.DONE); + this.trigger("load", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + this.trigger("loadend", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + }; + if (response.body) { + this.logger.info("mocked response has body, streaming..."); + const reader = response.body.getReader(); + const readNextResponseBodyChunk = async () => { + const { value, done } = await reader.read(); + if (done) { + this.logger.info("response body stream done!"); + finalizeResponse(); + return; + } + if (value) { + this.logger.info("read response body chunk:", value); + this.responseBuffer = concatArrayBuffer(this.responseBuffer, value); + this.trigger("progress", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + } + readNextResponseBodyChunk(); + }; + readNextResponseBodyChunk(); + } else { + finalizeResponse(); + } + } + responseBufferToText() { + return decodeBuffer(this.responseBuffer); + } + get response() { + this.logger.info( + "getResponse (responseType: %s)", + this.request.responseType + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + switch (this.request.responseType) { + case "json": { + const responseJson = parseJson(this.responseBufferToText()); + this.logger.info("resolved response JSON", responseJson); + return responseJson; + } + case "arraybuffer": { + const arrayBuffer = toArrayBuffer(this.responseBuffer); + this.logger.info("resolved response ArrayBuffer", arrayBuffer); + return arrayBuffer; + } + case "blob": { + const mimeType = this.request.getResponseHeader("Content-Type") || "text/plain"; + const responseBlob = new Blob([this.responseBufferToText()], { + type: mimeType + }); + this.logger.info( + "resolved response Blob (mime type: %s)", + responseBlob, + mimeType + ); + return responseBlob; + } + default: { + const responseText = this.responseBufferToText(); + this.logger.info( + 'resolving "%s" response type as text', + this.request.responseType, + responseText + ); + return responseText; + } + } + } + get responseText() { + invariant( + this.request.responseType === "" || this.request.responseType === "text", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.LOADING && this.request.readyState !== this.request.DONE) { + return ""; + } + const responseText = this.responseBufferToText(); + this.logger.info('getResponseText: "%s"', responseText); + return responseText; + } + get responseXML() { + invariant( + this.request.responseType === "" || this.request.responseType === "document", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + const contentType = this.request.getResponseHeader("Content-Type") || ""; + if (typeof DOMParser === "undefined") { + console.warn( + "Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly." + ); + return null; + } + if (isDomParserSupportedType(contentType)) { + return new DOMParser().parseFromString( + this.responseBufferToText(), + contentType + ); + } + return null; + } + errorWith(error) { + this[kIsRequestHandled] = true; + this.logger.info("responding with an error"); + this.setReadyState(this.request.DONE); + this.trigger("error", this.request); + this.trigger("loadend", this.request); + } + /** + * Transitions this request's `readyState` to the given one. + */ + setReadyState(nextReadyState) { + this.logger.info( + "setReadyState: %d -> %d", + this.request.readyState, + nextReadyState + ); + if (this.request.readyState === nextReadyState) { + this.logger.info("ready state identical, skipping transition..."); + return; + } + define(this.request, "readyState", nextReadyState); + this.logger.info("set readyState to: %d", nextReadyState); + if (nextReadyState !== this.request.UNSENT) { + this.logger.info('triggerring "readystatechange" event...'); + this.trigger("readystatechange", this.request); + } + } + /** + * Triggers given event on the `XMLHttpRequest` instance. + */ + trigger(eventName, target, options) { + const callback = target[`on${eventName}`]; + const event = createEvent(target, eventName, options); + this.logger.info('trigger "%s"', eventName, options || ""); + if (typeof callback === "function") { + this.logger.info('found a direct "%s" callback, calling...', eventName); + callback.call(target, event); + } + const events = target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events; + for (const [registeredEventName, listeners] of events) { + if (registeredEventName === eventName) { + this.logger.info( + 'found %d listener(s) for "%s" event, calling...', + listeners.length, + eventName + ); + listeners.forEach((listener) => listener.call(target, event)); + } + } + } + /** + * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance. + */ + toFetchApiRequest(body) { + this.logger.info("converting request to a Fetch API Request..."); + const resolvedBody = body instanceof Document ? body.documentElement.innerText : body; + const fetchRequest = new Request(this.url.href, { + method: this.method, + headers: this.requestHeaders, + /** + * @see https://xhr.spec.whatwg.org/#cross-origin-credentials + */ + credentials: this.request.withCredentials ? "include" : "same-origin", + body: ["GET", "HEAD"].includes(this.method.toUpperCase()) ? null : resolvedBody + }); + const proxyHeaders = createProxy(fetchRequest.headers, { + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "append": + case "set": { + const [headerName, headerValue] = args; + this.request.setRequestHeader(headerName, headerValue); + break; + } + case "delete": { + const [headerName] = args; + console.warn( + `XMLHttpRequest: Cannot remove a "${headerName}" header from the Fetch API representation of the "${fetchRequest.method} ${fetchRequest.url}" request. XMLHttpRequest headers cannot be removed.` + ); + break; + } + } + return invoke(); + } + }); + define(fetchRequest, "headers", proxyHeaders); + this.logger.info("converted request to a Fetch API Request!", fetchRequest); + return fetchRequest; + } +}; +kIsRequestHandled, kFetchRequest; +function toAbsoluteUrl(url) { + if (typeof location === "undefined") { + return new URL(url); + } + return new URL(url.toString(), location.href); +} +function define(target, property, value) { + Reflect.defineProperty(target, property, { + // Ensure writable properties to allow redefining readonly properties. + writable: true, + enumerable: true, + value + }); +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +function createXMLHttpRequestProxy({ + emitter, + logger +}) { + const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, { + construct(target, args, newTarget) { + logger.info("constructed new XMLHttpRequest"); + const originalRequest = Reflect.construct( + target, + args, + newTarget + ); + const prototypeDescriptors = Object.getOwnPropertyDescriptors( + target.prototype + ); + for (const propertyName in prototypeDescriptors) { + Reflect.defineProperty( + originalRequest, + propertyName, + prototypeDescriptors[propertyName] + ); + } + const xhrRequestController = new XMLHttpRequestController( + originalRequest, + logger + ); + xhrRequestController.onRequest = async function({ request, requestId }) { + const controller = new RequestController(request); + this.logger.info("awaiting mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + emitter.listenerCount("request") + ); + const isRequestHandled = await handleRequest({ + request, + requestId, + controller, + emitter, + onResponse: async (response) => { + await this.respondWith(response); + }, + onRequestError: () => { + this.errorWith(new TypeError("Network error")); + }, + onError: (error) => { + this.logger.info("request errored!", { error }); + if (error instanceof Error) { + this.errorWith(error); + } + } + }); + if (!isRequestHandled) { + this.logger.info( + "no mocked response received, performing request as-is..." + ); + } + }; + xhrRequestController.onResponse = async function({ + response, + isMockedResponse, + request, + requestId + }) { + this.logger.info( + 'emitting the "response" event for %s listener(s)...', + emitter.listenerCount("response") + ); + emitter.emit("response", { + response, + isMockedResponse, + request, + requestId + }); + }; + return xhrRequestController.request; + } + }); + return XMLHttpRequestProxy; +} + +// src/interceptors/XMLHttpRequest/index.ts +var _XMLHttpRequestInterceptor = class extends Interceptor { + constructor() { + super(_XMLHttpRequestInterceptor.interceptorSymbol); + } + checkEnvironment() { + return hasConfigurableGlobal("XMLHttpRequest"); + } + setup() { + const logger = this.logger.extend("setup"); + logger.info('patching "XMLHttpRequest" module...'); + const PureXMLHttpRequest = globalThis.XMLHttpRequest; + invariant2( + !PureXMLHttpRequest[IS_PATCHED_MODULE], + 'Failed to patch the "XMLHttpRequest" module: already patched.' + ); + globalThis.XMLHttpRequest = createXMLHttpRequestProxy({ + emitter: this.emitter, + logger: this.logger + }); + logger.info( + 'native "XMLHttpRequest" module patched!', + globalThis.XMLHttpRequest.name + ); + Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.XMLHttpRequest = PureXMLHttpRequest; + logger.info( + 'native "XMLHttpRequest" module restored!', + globalThis.XMLHttpRequest.name + ); + }); + } +}; +var XMLHttpRequestInterceptor = _XMLHttpRequestInterceptor; +XMLHttpRequestInterceptor.interceptorSymbol = Symbol("xhr"); + +export { + XMLHttpRequestInterceptor +}; +//# sourceMappingURL=chunk-DODHRDV6.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-DODHRDV6.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-DODHRDV6.mjs.map new file mode 100644 index 0000000000..085f069c19 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-DODHRDV6.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/XMLHttpRequest/index.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts","../../src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts","../../src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts","../../src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts","../../src/interceptors/XMLHttpRequest/utils/createEvent.ts","../../src/utils/findPropertySource.ts","../../src/utils/createProxy.ts","../../src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts","../../src/utils/parseJson.ts","../../src/interceptors/XMLHttpRequest/utils/createResponse.ts","../../src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { createXMLHttpRequestProxy } from './XMLHttpRequestProxy'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\n\nexport type XMLHttpRequestEmitter = Emitter\n\nexport class XMLHttpRequestInterceptor extends Interceptor {\n static interceptorSymbol = Symbol('xhr')\n\n constructor() {\n super(XMLHttpRequestInterceptor.interceptorSymbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('XMLHttpRequest')\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('patching \"XMLHttpRequest\" module...')\n\n const PureXMLHttpRequest = globalThis.XMLHttpRequest\n\n invariant(\n !(PureXMLHttpRequest as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"XMLHttpRequest\" module: already patched.'\n )\n\n globalThis.XMLHttpRequest = createXMLHttpRequestProxy({\n emitter: this.emitter,\n logger: this.logger,\n })\n\n logger.info(\n 'native \"XMLHttpRequest\" module patched!',\n globalThis.XMLHttpRequest.name\n )\n\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.XMLHttpRequest = PureXMLHttpRequest\n logger.info(\n 'native \"XMLHttpRequest\" module restored!',\n globalThis.XMLHttpRequest.name\n )\n })\n }\n}\n","import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport type { Logger } from '@open-draft/logger'\nimport { concatArrayBuffer } from './utils/concatArrayBuffer'\nimport { createEvent } from './utils/createEvent'\nimport {\n decodeBuffer,\n encodeBuffer,\n toArrayBuffer,\n} from '../../utils/bufferUtils'\nimport { createProxy } from '../../utils/createProxy'\nimport { isDomParserSupportedType } from './utils/isDomParserSupportedType'\nimport { parseJson } from '../../utils/parseJson'\nimport { createResponse } from './utils/createResponse'\nimport { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'\nimport { createRequestId } from '../../createRequestId'\nimport { getBodyByteLength } from './utils/getBodyByteLength'\n\nconst kIsRequestHandled = Symbol('kIsRequestHandled')\nconst IS_NODE = isNodeProcess()\nconst kFetchRequest = Symbol('kFetchRequest')\n\n/**\n * An `XMLHttpRequest` instance controller that allows us\n * to handle any given request instance (e.g. responding to it).\n */\nexport class XMLHttpRequestController {\n public request: XMLHttpRequest\n public requestId: string\n public onRequest?: (\n this: XMLHttpRequestController,\n args: {\n request: Request\n requestId: string\n }\n ) => Promise\n public onResponse?: (\n this: XMLHttpRequestController,\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ) => void;\n\n [kIsRequestHandled]: boolean;\n [kFetchRequest]?: Request\n private method: string = 'GET'\n private url: URL = null as any\n private requestHeaders: Headers\n private responseBuffer: Uint8Array\n private events: Map>\n private uploadEvents: Map<\n keyof XMLHttpRequestEventTargetEventMap,\n Array\n >\n\n constructor(readonly initialRequest: XMLHttpRequest, public logger: Logger) {\n this[kIsRequestHandled] = false\n\n this.events = new Map()\n this.uploadEvents = new Map()\n this.requestId = createRequestId()\n this.requestHeaders = new Headers()\n this.responseBuffer = new Uint8Array()\n\n this.request = createProxy(initialRequest, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'ontimeout': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n /**\n * @note Proxy callbacks to event listeners because JSDOM has trouble\n * translating these properties to callbacks. It seemed to be operating\n * on events exclusively.\n */\n this.request.addEventListener(eventName, nextValue as any)\n\n return invoke()\n }\n\n default: {\n return invoke()\n }\n }\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'open': {\n const [method, url] = args as [string, string | undefined]\n\n if (typeof url === 'undefined') {\n this.method = 'GET'\n this.url = toAbsoluteUrl(method)\n } else {\n this.method = method\n this.url = toAbsoluteUrl(url)\n }\n\n this.logger = this.logger.extend(`${this.method} ${this.url.href}`)\n this.logger.info('open', this.method, this.url.href)\n\n return invoke()\n }\n\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n\n this.registerEvent(eventName, listener)\n this.logger.info('addEventListener', eventName, listener)\n\n return invoke()\n }\n\n case 'setRequestHeader': {\n const [name, value] = args as [string, string]\n this.requestHeaders.set(name, value)\n\n this.logger.info('setRequestHeader', name, value)\n\n return invoke()\n }\n\n case 'send': {\n const [body] = args as [\n body?: XMLHttpRequestBodyInit | Document | null\n ]\n\n this.request.addEventListener('load', () => {\n if (typeof this.onResponse !== 'undefined') {\n // Create a Fetch API Response representation of whichever\n // response this XMLHttpRequest received. Note those may\n // be either a mocked and the original response.\n const fetchResponse = createResponse(\n this.request,\n /**\n * The `response` property is the right way to read\n * the ambiguous response body, as the request's \"responseType\" may differ.\n * @see https://xhr.spec.whatwg.org/#the-response-attribute\n */\n this.request.response\n )\n\n // Notify the consumer about the response.\n this.onResponse.call(this, {\n response: fetchResponse,\n isMockedResponse: this[kIsRequestHandled],\n request: fetchRequest,\n requestId: this.requestId!,\n })\n }\n })\n\n const requestBody =\n typeof body === 'string' ? encodeBuffer(body) : body\n\n // Delegate request handling to the consumer.\n const fetchRequest = this.toFetchApiRequest(requestBody)\n this[kFetchRequest] = fetchRequest.clone()\n\n const onceRequestSettled =\n this.onRequest?.call(this, {\n request: fetchRequest,\n requestId: this.requestId!,\n }) || Promise.resolve()\n\n onceRequestSettled.finally(() => {\n // If the consumer didn't handle the request (called `.respondWith()`) perform it as-is.\n if (!this[kIsRequestHandled]) {\n this.logger.info(\n 'request callback settled but request has not been handled (readystate %d), performing as-is...',\n this.request.readyState\n )\n\n /**\n * @note Set the intercepted request ID on the original request in Node.js\n * so that if it triggers any other interceptors, they don't attempt\n * to process it once again.\n *\n * For instance, XMLHttpRequest is often implemented via \"http.ClientRequest\"\n * and we don't want for both XHR and ClientRequest interceptors to\n * handle the same request at the same time (e.g. emit the \"response\" event twice).\n */\n if (IS_NODE) {\n this.request.setRequestHeader(\n INTERNAL_REQUEST_ID_HEADER_NAME,\n this.requestId!\n )\n }\n\n return invoke()\n }\n })\n\n break\n }\n\n default: {\n return invoke()\n }\n }\n },\n })\n\n /**\n * Proxy the `.upload` property to gather the event listeners/callbacks.\n */\n define(\n this.request,\n 'upload',\n createProxy(this.request.upload, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'onloadstart':\n case 'onprogress':\n case 'onaboart':\n case 'onerror':\n case 'onload':\n case 'ontimeout':\n case 'onloadend': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n this.registerUploadEvent(eventName, nextValue as Function)\n }\n }\n\n return invoke()\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n this.registerUploadEvent(eventName, listener)\n this.logger.info('upload.addEventListener', eventName, listener)\n\n return invoke()\n }\n }\n },\n })\n )\n }\n\n private registerEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.events.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.events.set(eventName, nextEvents)\n\n this.logger.info('registered event \"%s\"', eventName, listener)\n }\n\n private registerUploadEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.uploadEvents.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.uploadEvents.set(eventName, nextEvents)\n\n this.logger.info('registered upload event \"%s\"', eventName, listener)\n }\n\n /**\n * Responds to the current request with the given\n * Fetch API `Response` instance.\n */\n public async respondWith(response: Response): Promise {\n /**\n * @note Since `XMLHttpRequestController` delegates the handling of the responses\n * to the \"load\" event listener that doesn't distinguish between the mocked and original\n * responses, mark the request that had a mocked response with a corresponding symbol.\n *\n * Mark this request as having a mocked response immediately since\n * calculating request/response total body length is asynchronous.\n */\n this[kIsRequestHandled] = true\n\n /**\n * Dispatch request upload events for requests with a body.\n * @see https://github.com/mswjs/interceptors/issues/573\n */\n if (this[kFetchRequest]) {\n const totalRequestBodyLength = await getBodyByteLength(\n this[kFetchRequest]\n )\n\n this.trigger('loadstart', this.request.upload, {\n loaded: 0,\n total: totalRequestBodyLength,\n })\n this.trigger('progress', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('load', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('loadend', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n }\n\n this.logger.info(\n 'responding with a mocked response: %d %s',\n response.status,\n response.statusText\n )\n\n define(this.request, 'status', response.status)\n define(this.request, 'statusText', response.statusText)\n define(this.request, 'responseURL', this.url.href)\n\n this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, {\n apply: (_, __, args: [name: string]) => {\n this.logger.info('getResponseHeader', args[0])\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning null')\n\n // Headers not received yet, nothing to return.\n return null\n }\n\n const headerValue = response.headers.get(args[0])\n this.logger.info(\n 'resolved response header \"%s\" to',\n args[0],\n headerValue\n )\n\n return headerValue\n },\n })\n\n this.request.getAllResponseHeaders = new Proxy(\n this.request.getAllResponseHeaders,\n {\n apply: () => {\n this.logger.info('getAllResponseHeaders')\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning empty string')\n\n // Headers not received yet, nothing to return.\n return ''\n }\n\n const headersList = Array.from(response.headers.entries())\n const allHeaders = headersList\n .map(([headerName, headerValue]) => {\n return `${headerName}: ${headerValue}`\n })\n .join('\\r\\n')\n\n this.logger.info('resolved all response headers to', allHeaders)\n\n return allHeaders\n },\n }\n )\n\n // Update the response getters to resolve against the mocked response.\n Object.defineProperties(this.request, {\n response: {\n enumerable: true,\n configurable: false,\n get: () => this.response,\n },\n responseText: {\n enumerable: true,\n configurable: false,\n get: () => this.responseText,\n },\n responseXML: {\n enumerable: true,\n configurable: false,\n get: () => this.responseXML,\n },\n })\n\n const totalResponseBodyLength = await getBodyByteLength(response.clone())\n\n this.logger.info('calculated response body length', totalResponseBodyLength)\n\n this.trigger('loadstart', this.request, {\n loaded: 0,\n total: totalResponseBodyLength,\n })\n\n this.setReadyState(this.request.HEADERS_RECEIVED)\n this.setReadyState(this.request.LOADING)\n\n const finalizeResponse = () => {\n this.logger.info('finalizing the mocked response...')\n\n this.setReadyState(this.request.DONE)\n\n this.trigger('load', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n\n this.trigger('loadend', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n if (response.body) {\n this.logger.info('mocked response has body, streaming...')\n\n const reader = response.body.getReader()\n\n const readNextResponseBodyChunk = async () => {\n const { value, done } = await reader.read()\n\n if (done) {\n this.logger.info('response body stream done!')\n finalizeResponse()\n return\n }\n\n if (value) {\n this.logger.info('read response body chunk:', value)\n this.responseBuffer = concatArrayBuffer(this.responseBuffer, value)\n\n this.trigger('progress', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n readNextResponseBodyChunk()\n }\n\n readNextResponseBodyChunk()\n } else {\n finalizeResponse()\n }\n }\n\n private responseBufferToText(): string {\n return decodeBuffer(this.responseBuffer)\n }\n\n get response(): unknown {\n this.logger.info(\n 'getResponse (responseType: %s)',\n this.request.responseType\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n switch (this.request.responseType) {\n case 'json': {\n const responseJson = parseJson(this.responseBufferToText())\n this.logger.info('resolved response JSON', responseJson)\n\n return responseJson\n }\n\n case 'arraybuffer': {\n const arrayBuffer = toArrayBuffer(this.responseBuffer)\n this.logger.info('resolved response ArrayBuffer', arrayBuffer)\n\n return arrayBuffer\n }\n\n case 'blob': {\n const mimeType =\n this.request.getResponseHeader('Content-Type') || 'text/plain'\n const responseBlob = new Blob([this.responseBufferToText()], {\n type: mimeType,\n })\n\n this.logger.info(\n 'resolved response Blob (mime type: %s)',\n responseBlob,\n mimeType\n )\n\n return responseBlob\n }\n\n default: {\n const responseText = this.responseBufferToText()\n this.logger.info(\n 'resolving \"%s\" response type as text',\n this.request.responseType,\n responseText\n )\n\n return responseText\n }\n }\n }\n\n get responseText(): string {\n /**\n * Throw when trying to read the response body as text when the\n * \"responseType\" doesn't expect text. This just respects the spec better.\n * @see https://xhr.spec.whatwg.org/#the-responsetext-attribute\n */\n invariant(\n this.request.responseType === '' || this.request.responseType === 'text',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (\n this.request.readyState !== this.request.LOADING &&\n this.request.readyState !== this.request.DONE\n ) {\n return ''\n }\n\n const responseText = this.responseBufferToText()\n this.logger.info('getResponseText: \"%s\"', responseText)\n\n return responseText\n }\n\n get responseXML(): Document | null {\n invariant(\n this.request.responseType === '' ||\n this.request.responseType === 'document',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n const contentType = this.request.getResponseHeader('Content-Type') || ''\n\n if (typeof DOMParser === 'undefined') {\n console.warn(\n 'Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly.'\n )\n return null\n }\n\n if (isDomParserSupportedType(contentType)) {\n return new DOMParser().parseFromString(\n this.responseBufferToText(),\n contentType\n )\n }\n\n return null\n }\n\n public errorWith(error?: Error): void {\n /**\n * @note Mark this request as handled even if it received a mock error.\n * This prevents the controller from trying to perform this request as-is.\n */\n this[kIsRequestHandled] = true\n this.logger.info('responding with an error')\n\n this.setReadyState(this.request.DONE)\n this.trigger('error', this.request)\n this.trigger('loadend', this.request)\n }\n\n /**\n * Transitions this request's `readyState` to the given one.\n */\n private setReadyState(nextReadyState: number): void {\n this.logger.info(\n 'setReadyState: %d -> %d',\n this.request.readyState,\n nextReadyState\n )\n\n if (this.request.readyState === nextReadyState) {\n this.logger.info('ready state identical, skipping transition...')\n return\n }\n\n define(this.request, 'readyState', nextReadyState)\n\n this.logger.info('set readyState to: %d', nextReadyState)\n\n if (nextReadyState !== this.request.UNSENT) {\n this.logger.info('triggerring \"readystatechange\" event...')\n\n this.trigger('readystatechange', this.request)\n }\n }\n\n /**\n * Triggers given event on the `XMLHttpRequest` instance.\n */\n private trigger<\n EventName extends keyof (XMLHttpRequestEventTargetEventMap & {\n readystatechange: ProgressEvent\n })\n >(\n eventName: EventName,\n target: XMLHttpRequest | XMLHttpRequestUpload,\n options?: ProgressEventInit\n ): void {\n const callback = (target as XMLHttpRequest)[`on${eventName}`]\n const event = createEvent(target, eventName, options)\n\n this.logger.info('trigger \"%s\"', eventName, options || '')\n\n // Invoke direct callbacks.\n if (typeof callback === 'function') {\n this.logger.info('found a direct \"%s\" callback, calling...', eventName)\n callback.call(target as XMLHttpRequest, event)\n }\n\n // Invoke event listeners.\n const events =\n target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events\n\n for (const [registeredEventName, listeners] of events) {\n if (registeredEventName === eventName) {\n this.logger.info(\n 'found %d listener(s) for \"%s\" event, calling...',\n listeners.length,\n eventName\n )\n\n listeners.forEach((listener) => listener.call(target, event))\n }\n }\n }\n\n /**\n * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance.\n */\n private toFetchApiRequest(\n body: XMLHttpRequestBodyInit | Document | null | undefined\n ): Request {\n this.logger.info('converting request to a Fetch API Request...')\n\n // If the `Document` is used as the body of this XMLHttpRequest,\n // set its inner text as the Fetch API Request body.\n const resolvedBody =\n body instanceof Document ? body.documentElement.innerText : body\n\n const fetchRequest = new Request(this.url.href, {\n method: this.method,\n headers: this.requestHeaders,\n /**\n * @see https://xhr.spec.whatwg.org/#cross-origin-credentials\n */\n credentials: this.request.withCredentials ? 'include' : 'same-origin',\n body: ['GET', 'HEAD'].includes(this.method.toUpperCase())\n ? null\n : resolvedBody,\n })\n\n const proxyHeaders = createProxy(fetchRequest.headers, {\n methodCall: ([methodName, args], invoke) => {\n // Forward the latest state of the internal request headers\n // because the interceptor might have modified them\n // without responding to the request.\n switch (methodName) {\n case 'append':\n case 'set': {\n const [headerName, headerValue] = args as [string, string]\n this.request.setRequestHeader(headerName, headerValue)\n break\n }\n\n case 'delete': {\n const [headerName] = args as [string]\n console.warn(\n `XMLHttpRequest: Cannot remove a \"${headerName}\" header from the Fetch API representation of the \"${fetchRequest.method} ${fetchRequest.url}\" request. XMLHttpRequest headers cannot be removed.`\n )\n break\n }\n }\n\n return invoke()\n },\n })\n define(fetchRequest, 'headers', proxyHeaders)\n\n this.logger.info('converted request to a Fetch API Request!', fetchRequest)\n\n return fetchRequest\n }\n}\n\nfunction toAbsoluteUrl(url: string | URL): URL {\n /**\n * @note XMLHttpRequest interceptor may run in environments\n * that implement XMLHttpRequest but don't implement \"location\"\n * (for example, React Native). If that's the case, return the\n * input URL as-is (nothing to be relative to).\n * @see https://github.com/mswjs/msw/issues/1777\n */\n if (typeof location === 'undefined') {\n return new URL(url)\n }\n\n return new URL(url.toString(), location.href)\n}\n\nfunction define(\n target: object,\n property: string | symbol,\n value: unknown\n): void {\n Reflect.defineProperty(target, property, {\n // Ensure writable properties to allow redefining readonly properties.\n writable: true,\n enumerable: true,\n value,\n })\n}\n","/**\n * Concatenate two `Uint8Array` buffers.\n */\nexport function concatArrayBuffer(\n left: Uint8Array,\n right: Uint8Array\n): Uint8Array {\n const result = new Uint8Array(left.byteLength + right.byteLength)\n result.set(left, 0)\n result.set(right, left.byteLength)\n return result\n}\n","export class EventPolyfill implements Event {\n readonly NONE = 0\n readonly CAPTURING_PHASE = 1\n readonly AT_TARGET = 2\n readonly BUBBLING_PHASE = 3\n\n public type: string = ''\n public srcElement: EventTarget | null = null\n public target: EventTarget | null\n public currentTarget: EventTarget | null = null\n public eventPhase: number = 0\n public timeStamp: number\n public isTrusted: boolean = true\n public composed: boolean = false\n public cancelable: boolean = true\n public defaultPrevented: boolean = false\n public bubbles: boolean = true\n public lengthComputable: boolean = true\n public loaded: number = 0\n public total: number = 0\n\n cancelBubble: boolean = false\n returnValue: boolean = true\n\n constructor(\n type: string,\n options?: { target: EventTarget; currentTarget: EventTarget }\n ) {\n this.type = type\n this.target = options?.target || null\n this.currentTarget = options?.currentTarget || null\n this.timeStamp = Date.now()\n }\n\n public composedPath(): EventTarget[] {\n return []\n }\n\n public initEvent(type: string, bubbles?: boolean, cancelable?: boolean) {\n this.type = type\n this.bubbles = !!bubbles\n this.cancelable = !!cancelable\n }\n\n public preventDefault() {\n this.defaultPrevented = true\n }\n\n public stopPropagation() {}\n public stopImmediatePropagation() {}\n}\n","import { EventPolyfill } from './EventPolyfill'\n\nexport class ProgressEventPolyfill extends EventPolyfill {\n readonly lengthComputable: boolean\n readonly composed: boolean\n readonly loaded: number\n readonly total: number\n\n constructor(type: string, init?: ProgressEventInit) {\n super(type)\n\n this.lengthComputable = init?.lengthComputable || false\n this.composed = init?.composed || false\n this.loaded = init?.loaded || 0\n this.total = init?.total || 0\n }\n}\n","import { EventPolyfill } from '../polyfills/EventPolyfill'\nimport { ProgressEventPolyfill } from '../polyfills/ProgressEventPolyfill'\n\nconst SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== 'undefined'\n\nexport function createEvent(\n target: XMLHttpRequest | XMLHttpRequestUpload,\n type: string,\n init?: ProgressEventInit\n): EventPolyfill | ProgressEvent {\n const progressEvents = [\n 'error',\n 'progress',\n 'loadstart',\n 'loadend',\n 'load',\n 'timeout',\n 'abort',\n ]\n\n /**\n * `ProgressEvent` is not supported in React Native.\n * @see https://github.com/mswjs/interceptors/issues/40\n */\n const ProgressEventClass = SUPPORTS_PROGRESS_EVENT\n ? ProgressEvent\n : ProgressEventPolyfill\n\n const event = progressEvents.includes(type)\n ? new ProgressEventClass(type, {\n lengthComputable: true,\n loaded: init?.loaded || 0,\n total: init?.total || 0,\n })\n : new EventPolyfill(type, {\n target,\n currentTarget: target,\n })\n\n return event\n}\n","/**\n * Returns the source object of the given property on the target object\n * (the target itself, any parent in its prototype, or null).\n */\nexport function findPropertySource(\n target: object,\n propertyName: string | symbol\n): object | null {\n if (!(propertyName in target)) {\n return null\n }\n\n const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName)\n if (hasProperty) {\n return target\n }\n\n const prototype = Reflect.getPrototypeOf(target)\n return prototype ? findPropertySource(prototype, propertyName) : null\n}\n","import { findPropertySource } from './findPropertySource'\n\nexport interface ProxyOptions> {\n constructorCall?(args: Array, next: NextFunction): Target\n\n methodCall?(\n this: Target,\n data: [methodName: F, args: Array],\n next: NextFunction\n ): void\n\n setProperty?(\n data: [propertyName: string | symbol, nextValue: unknown],\n next: NextFunction\n ): boolean\n\n getProperty?(\n data: [propertyName: string | symbol, receiver: Target],\n next: NextFunction\n ): void\n}\n\nexport type NextFunction = () => ReturnType\n\nexport function createProxy(\n target: Target,\n options: ProxyOptions\n): Target {\n const proxy = new Proxy(target, optionsToProxyHandler(options))\n\n return proxy\n}\n\nfunction optionsToProxyHandler>(\n options: ProxyOptions\n): ProxyHandler {\n const { constructorCall, methodCall, getProperty, setProperty } = options\n const handler: ProxyHandler = {}\n\n if (typeof constructorCall !== 'undefined') {\n handler.construct = function (target, args, newTarget) {\n const next = Reflect.construct.bind(null, target as any, args, newTarget)\n return constructorCall.call(newTarget, args, next)\n }\n }\n\n handler.set = function (target, propertyName, nextValue) {\n const next = () => {\n const propertySource = findPropertySource(target, propertyName) || target\n const ownDescriptors = Reflect.getOwnPropertyDescriptor(\n propertySource,\n propertyName\n )\n\n // Respect any custom setters present for this property.\n if (typeof ownDescriptors?.set !== 'undefined') {\n ownDescriptors.set.apply(target, [nextValue])\n return true\n }\n\n // Otherwise, set the property on the source.\n return Reflect.defineProperty(propertySource, propertyName, {\n writable: true,\n enumerable: true,\n configurable: true,\n value: nextValue,\n })\n }\n\n if (typeof setProperty !== 'undefined') {\n return setProperty.call(target, [propertyName, nextValue], next)\n }\n\n return next()\n }\n\n handler.get = function (target, propertyName, receiver) {\n /**\n * @note Using `Reflect.get()` here causes \"TypeError: Illegal invocation\".\n */\n const next = () => target[propertyName as any]\n\n const value =\n typeof getProperty !== 'undefined'\n ? getProperty.call(target, [propertyName, receiver], next)\n : next()\n\n if (typeof value === 'function') {\n return (...args: Array) => {\n const next = value.bind(target, ...args)\n\n if (typeof methodCall !== 'undefined') {\n return methodCall.call(target, [propertyName as any, args], next)\n }\n\n return next()\n }\n }\n\n return value\n }\n\n return handler\n}\n","export function isDomParserSupportedType(\n type: string\n): type is DOMParserSupportedType {\n const supportedTypes: Array = [\n 'application/xhtml+xml',\n 'application/xml',\n 'image/svg+xml',\n 'text/html',\n 'text/xml',\n ]\n return supportedTypes.some((supportedType) => {\n return type.startsWith(supportedType)\n })\n}\n","/**\n * Parses a given string into JSON.\n * Gracefully handles invalid JSON by returning `null`.\n */\nexport function parseJson(data: string): Record | null {\n try {\n const json = JSON.parse(data)\n return json\n } catch (_) {\n return null\n }\n}\n","import { FetchResponse } from '../../../utils/fetchUtils'\n\n/**\n * Creates a Fetch API `Response` instance from the given\n * `XMLHttpRequest` instance and a response body.\n */\nexport function createResponse(\n request: XMLHttpRequest,\n body: BodyInit | null\n): Response {\n /**\n * Handle XMLHttpRequest responses that must have null as the\n * response body when represented using Fetch API Response.\n * XMLHttpRequest response will always have an empty string\n * as the \"request.response\" in those cases, resulting in an error\n * when constructing a Response instance.\n * @see https://github.com/mswjs/interceptors/issues/379\n */\n const responseBodyOrNull = FetchResponse.isResponseWithBody(request.status)\n ? body\n : null\n\n return new FetchResponse(responseBodyOrNull, {\n url: request.responseURL,\n status: request.status,\n statusText: request.statusText,\n headers: createHeadersFromXMLHttpReqestHeaders(\n request.getAllResponseHeaders()\n ),\n })\n}\n\nfunction createHeadersFromXMLHttpReqestHeaders(headersString: string): Headers {\n const headers = new Headers()\n\n const lines = headersString.split(/[\\r\\n]+/)\n for (const line of lines) {\n if (line.trim() === '') {\n continue\n }\n\n const [name, ...parts] = line.split(': ')\n const value = parts.join(': ')\n\n headers.append(name, value)\n }\n\n return headers\n}\n","/**\n * Return a total byte length of the given request/response body.\n * If the `Content-Length` header is present, it will be used as the byte length.\n */\nexport async function getBodyByteLength(\n input: Request | Response\n): Promise {\n const explicitContentLength = input.headers.get('content-length')\n\n if (explicitContentLength != null && explicitContentLength !== '') {\n return Number(explicitContentLength)\n }\n\n const buffer = await input.arrayBuffer()\n return buffer.byteLength\n}\n","import type { Logger } from '@open-draft/logger'\nimport { XMLHttpRequestEmitter } from '.'\nimport { RequestController } from '../../RequestController'\nimport { XMLHttpRequestController } from './XMLHttpRequestController'\nimport { handleRequest } from '../../utils/handleRequest'\n\nexport interface XMLHttpRequestProxyOptions {\n emitter: XMLHttpRequestEmitter\n logger: Logger\n}\n\n/**\n * Create a proxied `XMLHttpRequest` class.\n * The proxied class establishes spies on certain methods,\n * allowing us to intercept requests and respond to them.\n */\nexport function createXMLHttpRequestProxy({\n emitter,\n logger,\n}: XMLHttpRequestProxyOptions) {\n const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {\n construct(target, args, newTarget) {\n logger.info('constructed new XMLHttpRequest')\n\n const originalRequest = Reflect.construct(\n target,\n args,\n newTarget\n ) as XMLHttpRequest\n\n /**\n * @note Forward prototype descriptors onto the proxied object.\n * XMLHttpRequest is implemented in JSDOM in a way that assigns\n * a bunch of descriptors, like \"set responseType()\" on the prototype.\n * With this propagation, we make sure that those descriptors trigger\n * when the user operates with the proxied request instance.\n */\n const prototypeDescriptors = Object.getOwnPropertyDescriptors(\n target.prototype\n )\n for (const propertyName in prototypeDescriptors) {\n Reflect.defineProperty(\n originalRequest,\n propertyName,\n prototypeDescriptors[propertyName]\n )\n }\n\n const xhrRequestController = new XMLHttpRequestController(\n originalRequest,\n logger\n )\n\n xhrRequestController.onRequest = async function ({ request, requestId }) {\n const controller = new RequestController(request)\n\n this.logger.info('awaiting mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n controller,\n emitter,\n onResponse: async (response) => {\n await this.respondWith(response)\n },\n onRequestError: () => {\n this.errorWith(new TypeError('Network error'))\n },\n onError: (error) => {\n this.logger.info('request errored!', { error })\n\n if (error instanceof Error) {\n this.errorWith(error)\n }\n },\n })\n\n if (!isRequestHandled) {\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n }\n }\n\n xhrRequestController.onResponse = async function ({\n response,\n isMockedResponse,\n request,\n requestId,\n }) {\n this.logger.info(\n 'emitting the \"response\" event for %s listener(s)...',\n emitter.listenerCount('response')\n )\n\n emitter.emit('response', {\n response,\n isMockedResponse,\n request,\n requestId,\n })\n }\n\n // Return the proxied request from the controller\n // so that the controller can react to the consumer's interactions\n // with this request (opening/sending/etc).\n return xhrRequestController.request\n },\n })\n\n return XMLHttpRequestProxy\n}\n"],"mappings":"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","names":["invariant","next","invariant"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-FGSEOIC4.js b/node_modules/@mswjs/interceptors/lib/browser/chunk-FGSEOIC4.js new file mode 100644 index 0000000000..b95c747ba4 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-FGSEOIC4.js @@ -0,0 +1,228 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/RequestController.ts +var _outvariant = require('outvariant'); +var _deferredpromise = require('@open-draft/deferred-promise'); + +// src/InterceptorError.ts +var InterceptorError = class extends Error { + constructor(message) { + super(message); + this.name = "InterceptorError"; + Object.setPrototypeOf(this, InterceptorError.prototype); + } +}; + +// src/RequestController.ts +var kRequestHandled = Symbol("kRequestHandled"); +var kResponsePromise = Symbol("kResponsePromise"); +var RequestController = class { + constructor(request) { + this.request = request; + this[kRequestHandled] = false; + this[kResponsePromise] = new (0, _deferredpromise.DeferredPromise)(); + } + /** + * Respond to this request with the given `Response` instance. + * @example + * controller.respondWith(new Response()) + * controller.respondWith(Response.json({ id })) + * controller.respondWith(Response.error()) + */ + respondWith(response) { + _outvariant.invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to respond to the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(response); + } + /** + * Error this request with the given error. + * @example + * controller.errorWith() + * controller.errorWith(new Error('Oops!')) + */ + errorWith(error) { + _outvariant.invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to error the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(error); + } +}; +kResponsePromise, kRequestHandled; + +// src/utils/emitAsync.ts +async function emitAsync(emitter, eventName, ...data) { + const listners = emitter.listeners(eventName); + if (listners.length === 0) { + return; + } + for (const listener of listners) { + await listener.apply(emitter, data); + } +} + +// src/utils/handleRequest.ts + +var _until = require('@open-draft/until'); + +// src/utils/isPropertyAccessible.ts +function isPropertyAccessible(obj, key) { + try { + obj[key]; + return true; + } catch (e) { + return false; + } +} + +// src/utils/responseUtils.ts +function createServerErrorResponse(body) { + return new Response( + JSON.stringify( + body instanceof Error ? { + name: body.name, + message: body.message, + stack: body.stack + } : body + ), + { + status: 500, + statusText: "Unhandled Exception", + headers: { + "Content-Type": "application/json" + } + } + ); +} +function isResponseError(response) { + return isPropertyAccessible(response, "type") && response.type === "error"; +} + +// src/utils/isNodeLikeError.ts +function isNodeLikeError(error) { + if (error == null) { + return false; + } + if (!(error instanceof Error)) { + return false; + } + return "code" in error && "errno" in error; +} + +// src/utils/handleRequest.ts +async function handleRequest(options) { + const handleResponse = async (response) => { + if (response instanceof Error) { + options.onError(response); + } else if (isResponseError(response)) { + options.onRequestError(response); + } else { + await options.onResponse(response); + } + return true; + }; + const handleResponseError = async (error) => { + if (error instanceof InterceptorError) { + throw result.error; + } + if (isNodeLikeError(error)) { + options.onError(error); + return true; + } + if (error instanceof Response) { + return await handleResponse(error); + } + return false; + }; + options.emitter.once("request", ({ requestId: pendingRequestId }) => { + if (pendingRequestId !== options.requestId) { + return; + } + if (options.controller[kResponsePromise].state === "pending") { + options.controller[kResponsePromise].resolve(void 0); + } + }); + const requestAbortPromise = new (0, _deferredpromise.DeferredPromise)(); + if (options.request.signal) { + if (options.request.signal.aborted) { + requestAbortPromise.reject(options.request.signal.reason); + } else { + options.request.signal.addEventListener( + "abort", + () => { + requestAbortPromise.reject(options.request.signal.reason); + }, + { once: true } + ); + } + } + const result = await _until.until.call(void 0, async () => { + const requestListtenersPromise = emitAsync(options.emitter, "request", { + requestId: options.requestId, + request: options.request, + controller: options.controller + }); + await Promise.race([ + // Short-circuit the request handling promise if the request gets aborted. + requestAbortPromise, + requestListtenersPromise, + options.controller[kResponsePromise] + ]); + const mockedResponse = await options.controller[kResponsePromise]; + return mockedResponse; + }); + if (requestAbortPromise.state === "rejected") { + options.onError(requestAbortPromise.rejectionReason); + return true; + } + if (result.error) { + if (await handleResponseError(result.error)) { + return true; + } + if (options.emitter.listenerCount("unhandledException") > 0) { + const unhandledExceptionController = new RequestController( + options.request + ); + await emitAsync(options.emitter, "unhandledException", { + error: result.error, + request: options.request, + requestId: options.requestId, + controller: unhandledExceptionController + }).then(() => { + if (unhandledExceptionController[kResponsePromise].state === "pending") { + unhandledExceptionController[kResponsePromise].resolve(void 0); + } + }); + const nextResult = await _until.until.call(void 0, + () => unhandledExceptionController[kResponsePromise] + ); + if (nextResult.error) { + return handleResponseError(nextResult.error); + } + if (nextResult.data) { + return handleResponse(nextResult.data); + } + } + options.onResponse(createServerErrorResponse(result.error)); + return true; + } + if (result.data) { + return handleResponse(result.data); + } + return false; +} + + + + + +exports.RequestController = RequestController; exports.emitAsync = emitAsync; exports.handleRequest = handleRequest; +//# sourceMappingURL=chunk-FGSEOIC4.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-FGSEOIC4.js.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-FGSEOIC4.js.map new file mode 100644 index 0000000000..9c5a436574 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-FGSEOIC4.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/RequestController.ts","../../src/InterceptorError.ts","../../src/utils/emitAsync.ts","../../src/utils/handleRequest.ts","../../src/utils/isPropertyAccessible.ts","../../src/utils/responseUtils.ts","../../src/utils/isNodeLikeError.ts"],"names":["DeferredPromise"],"mappings":"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","sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { InterceptorError } from './InterceptorError'\n\nconst kRequestHandled = Symbol('kRequestHandled')\nexport const kResponsePromise = Symbol('kResponsePromise')\n\nexport class RequestController {\n /**\n * Internal response promise.\n * Available only for the library internals to grab the\n * response instance provided by the developer.\n * @note This promise cannot be rejected. It's either infinitely\n * pending or resolved with whichever Response was passed to `respondWith()`.\n */\n [kResponsePromise]: DeferredPromise;\n\n /**\n * Internal flag indicating if this request has been handled.\n * @note The response promise becomes \"fulfilled\" on the next tick.\n */\n [kRequestHandled]: boolean\n\n constructor(private request: Request) {\n this[kRequestHandled] = false\n this[kResponsePromise] = new DeferredPromise()\n }\n\n /**\n * Respond to this request with the given `Response` instance.\n * @example\n * controller.respondWith(new Response())\n * controller.respondWith(Response.json({ id }))\n * controller.respondWith(Response.error())\n */\n public respondWith(response: Response): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to respond to the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n this[kResponsePromise].resolve(response)\n\n /**\n * @note The request conrtoller doesn't do anything\n * apart from letting the interceptor await the response\n * provided by the developer through the response promise.\n * Each interceptor implements the actual respondWith/errorWith\n * logic based on that interceptor's needs.\n */\n }\n\n /**\n * Error this request with the given error.\n * @example\n * controller.errorWith()\n * controller.errorWith(new Error('Oops!'))\n */\n public errorWith(error?: Error): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to error the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n\n /**\n * @note Resolve the response promise, not reject.\n * This helps us differentiate between unhandled exceptions\n * and intended errors (\"errorWith\") while waiting for the response.\n */\n this[kResponsePromise].resolve(error)\n }\n}\n","export class InterceptorError extends Error {\n constructor(message?: string) {\n super(message)\n this.name = 'InterceptorError'\n Object.setPrototypeOf(this, InterceptorError.prototype)\n }\n}\n","import { Emitter, EventMap } from 'strict-event-emitter'\n\n/**\n * Emits an event on the given emitter but executes\n * the listeners sequentially. This accounts for asynchronous\n * listeners (e.g. those having \"sleep\" and handling the request).\n */\nexport async function emitAsync<\n Events extends EventMap,\n EventName extends keyof Events\n>(\n emitter: Emitter,\n eventName: EventName,\n ...data: Events[EventName]\n): Promise {\n const listners = emitter.listeners(eventName)\n\n if (listners.length === 0) {\n return\n }\n\n for (const listener of listners) {\n await listener.apply(emitter, data)\n }\n}\n","import type { Emitter } from 'strict-event-emitter'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport type { HttpRequestEventMap } from '../glossary'\nimport { emitAsync } from './emitAsync'\nimport { kResponsePromise, RequestController } from '../RequestController'\nimport {\n createServerErrorResponse,\n isResponseError,\n ResponseError,\n} from './responseUtils'\nimport { InterceptorError } from '../InterceptorError'\nimport { isNodeLikeError } from './isNodeLikeError'\n\ninterface HandleRequestOptions {\n requestId: string\n request: Request\n emitter: Emitter\n controller: RequestController\n\n /**\n * Called when the request has been handled\n * with the given `Response` instance.\n */\n onResponse: (response: Response) => void | Promise\n\n /**\n * Called when the request has been handled\n * with the given `Response.error()` instance.\n */\n onRequestError: (response: ResponseError) => void\n\n /**\n * Called when an unhandled error happens during the\n * request handling. This is never a thrown error/response.\n */\n onError: (error: unknown) => void\n}\n\n/**\n * @returns {Promise} Indicates whether the request has been handled.\n */\nexport async function handleRequest(\n options: HandleRequestOptions\n): Promise {\n const handleResponse = async (response: Response | Error) => {\n if (response instanceof Error) {\n options.onError(response)\n }\n\n // Handle \"Response.error()\" instances.\n else if (isResponseError(response)) {\n options.onRequestError(response)\n } else {\n await options.onResponse(response)\n }\n\n return true\n }\n\n const handleResponseError = async (error: unknown): Promise => {\n // Forward the special interceptor error instances\n // to the developer. These must not be handled in any way.\n if (error instanceof InterceptorError) {\n throw result.error\n }\n\n // Support mocking Node.js-like errors.\n if (isNodeLikeError(error)) {\n options.onError(error)\n return true\n }\n\n // Handle thrown responses.\n if (error instanceof Response) {\n return await handleResponse(error)\n }\n\n return false\n }\n\n // Add the last \"request\" listener to check if the request\n // has been handled in any way. If it hasn't, resolve the\n // response promise with undefined.\n options.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== options.requestId) {\n return\n }\n\n if (options.controller[kResponsePromise].state === 'pending') {\n options.controller[kResponsePromise].resolve(undefined)\n }\n })\n\n const requestAbortPromise = new DeferredPromise()\n\n /**\n * @note `signal` is not always defined in React Native.\n */\n if (options.request.signal) {\n if (options.request.signal.aborted) {\n requestAbortPromise.reject(options.request.signal.reason)\n } else {\n options.request.signal.addEventListener(\n 'abort',\n () => {\n requestAbortPromise.reject(options.request.signal.reason)\n },\n { once: true }\n )\n }\n }\n\n const result = await until(async () => {\n // Emit the \"request\" event and wait until all the listeners\n // for that event are finished (e.g. async listeners awaited).\n // By the end of this promise, the developer cannot affect the\n // request anymore.\n const requestListtenersPromise = emitAsync(options.emitter, 'request', {\n requestId: options.requestId,\n request: options.request,\n controller: options.controller,\n })\n\n await Promise.race([\n // Short-circuit the request handling promise if the request gets aborted.\n requestAbortPromise,\n requestListtenersPromise,\n options.controller[kResponsePromise],\n ])\n\n // The response promise will settle immediately once\n // the developer calls either \"respondWith\" or \"errorWith\".\n const mockedResponse = await options.controller[kResponsePromise]\n return mockedResponse\n })\n\n // Handle the request being aborted while waiting for the request listeners.\n if (requestAbortPromise.state === 'rejected') {\n options.onError(requestAbortPromise.rejectionReason)\n return true\n }\n\n if (result.error) {\n // Handle the error during the request listener execution.\n // These can be thrown responses or request errors.\n if (await handleResponseError(result.error)) {\n return true\n }\n\n // If the developer has added \"unhandledException\" listeners,\n // allow them to handle the error. They can translate it to a\n // mocked response, network error, or forward it as-is.\n if (options.emitter.listenerCount('unhandledException') > 0) {\n // Create a new request controller just for the unhandled exception case.\n // This is needed because the original controller might have been already\n // interacted with (e.g. \"respondWith\" or \"errorWith\" called on it).\n const unhandledExceptionController = new RequestController(\n options.request\n )\n\n await emitAsync(options.emitter, 'unhandledException', {\n error: result.error,\n request: options.request,\n requestId: options.requestId,\n controller: unhandledExceptionController,\n }).then(() => {\n // If all the \"unhandledException\" listeners have finished\n // but have not handled the response in any way, preemptively\n // resolve the pending response promise from the new controller.\n // This prevents it from hanging forever.\n if (\n unhandledExceptionController[kResponsePromise].state === 'pending'\n ) {\n unhandledExceptionController[kResponsePromise].resolve(undefined)\n }\n })\n\n const nextResult = await until(\n () => unhandledExceptionController[kResponsePromise]\n )\n\n /**\n * @note Handle the result of the unhandled controller\n * in the same way as the original request controller.\n * The exception here is that thrown errors within the\n * \"unhandledException\" event do NOT result in another\n * emit of the same event. They are forwarded as-is.\n */\n if (nextResult.error) {\n return handleResponseError(nextResult.error)\n }\n\n if (nextResult.data) {\n return handleResponse(nextResult.data)\n }\n }\n\n // Otherwise, coerce unhandled exceptions to a 500 Internal Server Error response.\n options.onResponse(createServerErrorResponse(result.error))\n return true\n }\n\n /**\n * Handle a mocked Response instance.\n * @note That this can also be an Error in case\n * the developer called \"errorWith\". This differentiates\n * unhandled exceptions from intended errors.\n */\n if (result.data) {\n return handleResponse(result.data)\n }\n\n // In all other cases, consider the request unhandled.\n // The interceptor must perform it as-is.\n return false\n}\n","/**\n * A function that validates if property access is possible on an object\n * without throwing. It returns `true` if the property access is possible\n * and `false` otherwise.\n *\n * Environments like miniflare will throw on property access on certain objects\n * like Request and Response, for unimplemented properties.\n */\nexport function isPropertyAccessible>(\n obj: Obj,\n key: keyof Obj\n) {\n try {\n obj[key]\n return true\n } catch {\n return false\n }\n}\n","import { isPropertyAccessible } from './isPropertyAccessible'\n\n/**\n * Creates a generic 500 Unhandled Exception response.\n */\nexport function createServerErrorResponse(body: unknown): Response {\n return new Response(\n JSON.stringify(\n body instanceof Error\n ? {\n name: body.name,\n message: body.message,\n stack: body.stack,\n }\n : body\n ),\n {\n status: 500,\n statusText: 'Unhandled Exception',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n}\n\nexport type ResponseError = Response & { type: 'error' }\n\n/**\n * Check if the given response is a `Response.error()`.\n *\n * @note Some environments, like Miniflare (Cloudflare) do not\n * implement the \"Response.type\" property and throw on its access.\n * Safely check if we can access \"type\" on \"Response\" before continuing.\n * @see https://github.com/mswjs/msw/issues/1834\n */\nexport function isResponseError(response: Response): response is ResponseError {\n return isPropertyAccessible(response, 'type') && response.type === 'error'\n}\n","export function isNodeLikeError(\n error: unknown\n): error is NodeJS.ErrnoException {\n if (error == null) {\n return false\n }\n\n if (!(error instanceof Error)) {\n return false\n }\n\n return 'code' in error && 'errno' in error\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-H5O73WD2.mjs b/node_modules/@mswjs/interceptors/lib/browser/chunk-H5O73WD2.mjs new file mode 100644 index 0000000000..193b4416ef --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-H5O73WD2.mjs @@ -0,0 +1,228 @@ +// src/RequestController.ts +import { invariant } from "outvariant"; +import { DeferredPromise } from "@open-draft/deferred-promise"; + +// src/InterceptorError.ts +var InterceptorError = class extends Error { + constructor(message) { + super(message); + this.name = "InterceptorError"; + Object.setPrototypeOf(this, InterceptorError.prototype); + } +}; + +// src/RequestController.ts +var kRequestHandled = Symbol("kRequestHandled"); +var kResponsePromise = Symbol("kResponsePromise"); +var RequestController = class { + constructor(request) { + this.request = request; + this[kRequestHandled] = false; + this[kResponsePromise] = new DeferredPromise(); + } + /** + * Respond to this request with the given `Response` instance. + * @example + * controller.respondWith(new Response()) + * controller.respondWith(Response.json({ id })) + * controller.respondWith(Response.error()) + */ + respondWith(response) { + invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to respond to the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(response); + } + /** + * Error this request with the given error. + * @example + * controller.errorWith() + * controller.errorWith(new Error('Oops!')) + */ + errorWith(error) { + invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to error the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(error); + } +}; +kResponsePromise, kRequestHandled; + +// src/utils/emitAsync.ts +async function emitAsync(emitter, eventName, ...data) { + const listners = emitter.listeners(eventName); + if (listners.length === 0) { + return; + } + for (const listener of listners) { + await listener.apply(emitter, data); + } +} + +// src/utils/handleRequest.ts +import { DeferredPromise as DeferredPromise2 } from "@open-draft/deferred-promise"; +import { until } from "@open-draft/until"; + +// src/utils/isPropertyAccessible.ts +function isPropertyAccessible(obj, key) { + try { + obj[key]; + return true; + } catch (e) { + return false; + } +} + +// src/utils/responseUtils.ts +function createServerErrorResponse(body) { + return new Response( + JSON.stringify( + body instanceof Error ? { + name: body.name, + message: body.message, + stack: body.stack + } : body + ), + { + status: 500, + statusText: "Unhandled Exception", + headers: { + "Content-Type": "application/json" + } + } + ); +} +function isResponseError(response) { + return isPropertyAccessible(response, "type") && response.type === "error"; +} + +// src/utils/isNodeLikeError.ts +function isNodeLikeError(error) { + if (error == null) { + return false; + } + if (!(error instanceof Error)) { + return false; + } + return "code" in error && "errno" in error; +} + +// src/utils/handleRequest.ts +async function handleRequest(options) { + const handleResponse = async (response) => { + if (response instanceof Error) { + options.onError(response); + } else if (isResponseError(response)) { + options.onRequestError(response); + } else { + await options.onResponse(response); + } + return true; + }; + const handleResponseError = async (error) => { + if (error instanceof InterceptorError) { + throw result.error; + } + if (isNodeLikeError(error)) { + options.onError(error); + return true; + } + if (error instanceof Response) { + return await handleResponse(error); + } + return false; + }; + options.emitter.once("request", ({ requestId: pendingRequestId }) => { + if (pendingRequestId !== options.requestId) { + return; + } + if (options.controller[kResponsePromise].state === "pending") { + options.controller[kResponsePromise].resolve(void 0); + } + }); + const requestAbortPromise = new DeferredPromise2(); + if (options.request.signal) { + if (options.request.signal.aborted) { + requestAbortPromise.reject(options.request.signal.reason); + } else { + options.request.signal.addEventListener( + "abort", + () => { + requestAbortPromise.reject(options.request.signal.reason); + }, + { once: true } + ); + } + } + const result = await until(async () => { + const requestListtenersPromise = emitAsync(options.emitter, "request", { + requestId: options.requestId, + request: options.request, + controller: options.controller + }); + await Promise.race([ + // Short-circuit the request handling promise if the request gets aborted. + requestAbortPromise, + requestListtenersPromise, + options.controller[kResponsePromise] + ]); + const mockedResponse = await options.controller[kResponsePromise]; + return mockedResponse; + }); + if (requestAbortPromise.state === "rejected") { + options.onError(requestAbortPromise.rejectionReason); + return true; + } + if (result.error) { + if (await handleResponseError(result.error)) { + return true; + } + if (options.emitter.listenerCount("unhandledException") > 0) { + const unhandledExceptionController = new RequestController( + options.request + ); + await emitAsync(options.emitter, "unhandledException", { + error: result.error, + request: options.request, + requestId: options.requestId, + controller: unhandledExceptionController + }).then(() => { + if (unhandledExceptionController[kResponsePromise].state === "pending") { + unhandledExceptionController[kResponsePromise].resolve(void 0); + } + }); + const nextResult = await until( + () => unhandledExceptionController[kResponsePromise] + ); + if (nextResult.error) { + return handleResponseError(nextResult.error); + } + if (nextResult.data) { + return handleResponse(nextResult.data); + } + } + options.onResponse(createServerErrorResponse(result.error)); + return true; + } + if (result.data) { + return handleResponse(result.data); + } + return false; +} + +export { + RequestController, + emitAsync, + handleRequest +}; +//# sourceMappingURL=chunk-H5O73WD2.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-H5O73WD2.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-H5O73WD2.mjs.map new file mode 100644 index 0000000000..41215da760 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-H5O73WD2.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/RequestController.ts","../../src/InterceptorError.ts","../../src/utils/emitAsync.ts","../../src/utils/handleRequest.ts","../../src/utils/isPropertyAccessible.ts","../../src/utils/responseUtils.ts","../../src/utils/isNodeLikeError.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { InterceptorError } from './InterceptorError'\n\nconst kRequestHandled = Symbol('kRequestHandled')\nexport const kResponsePromise = Symbol('kResponsePromise')\n\nexport class RequestController {\n /**\n * Internal response promise.\n * Available only for the library internals to grab the\n * response instance provided by the developer.\n * @note This promise cannot be rejected. It's either infinitely\n * pending or resolved with whichever Response was passed to `respondWith()`.\n */\n [kResponsePromise]: DeferredPromise;\n\n /**\n * Internal flag indicating if this request has been handled.\n * @note The response promise becomes \"fulfilled\" on the next tick.\n */\n [kRequestHandled]: boolean\n\n constructor(private request: Request) {\n this[kRequestHandled] = false\n this[kResponsePromise] = new DeferredPromise()\n }\n\n /**\n * Respond to this request with the given `Response` instance.\n * @example\n * controller.respondWith(new Response())\n * controller.respondWith(Response.json({ id }))\n * controller.respondWith(Response.error())\n */\n public respondWith(response: Response): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to respond to the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n this[kResponsePromise].resolve(response)\n\n /**\n * @note The request conrtoller doesn't do anything\n * apart from letting the interceptor await the response\n * provided by the developer through the response promise.\n * Each interceptor implements the actual respondWith/errorWith\n * logic based on that interceptor's needs.\n */\n }\n\n /**\n * Error this request with the given error.\n * @example\n * controller.errorWith()\n * controller.errorWith(new Error('Oops!'))\n */\n public errorWith(error?: Error): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to error the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n\n /**\n * @note Resolve the response promise, not reject.\n * This helps us differentiate between unhandled exceptions\n * and intended errors (\"errorWith\") while waiting for the response.\n */\n this[kResponsePromise].resolve(error)\n }\n}\n","export class InterceptorError extends Error {\n constructor(message?: string) {\n super(message)\n this.name = 'InterceptorError'\n Object.setPrototypeOf(this, InterceptorError.prototype)\n }\n}\n","import { Emitter, EventMap } from 'strict-event-emitter'\n\n/**\n * Emits an event on the given emitter but executes\n * the listeners sequentially. This accounts for asynchronous\n * listeners (e.g. those having \"sleep\" and handling the request).\n */\nexport async function emitAsync<\n Events extends EventMap,\n EventName extends keyof Events\n>(\n emitter: Emitter,\n eventName: EventName,\n ...data: Events[EventName]\n): Promise {\n const listners = emitter.listeners(eventName)\n\n if (listners.length === 0) {\n return\n }\n\n for (const listener of listners) {\n await listener.apply(emitter, data)\n }\n}\n","import type { Emitter } from 'strict-event-emitter'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport type { HttpRequestEventMap } from '../glossary'\nimport { emitAsync } from './emitAsync'\nimport { kResponsePromise, RequestController } from '../RequestController'\nimport {\n createServerErrorResponse,\n isResponseError,\n ResponseError,\n} from './responseUtils'\nimport { InterceptorError } from '../InterceptorError'\nimport { isNodeLikeError } from './isNodeLikeError'\n\ninterface HandleRequestOptions {\n requestId: string\n request: Request\n emitter: Emitter\n controller: RequestController\n\n /**\n * Called when the request has been handled\n * with the given `Response` instance.\n */\n onResponse: (response: Response) => void | Promise\n\n /**\n * Called when the request has been handled\n * with the given `Response.error()` instance.\n */\n onRequestError: (response: ResponseError) => void\n\n /**\n * Called when an unhandled error happens during the\n * request handling. This is never a thrown error/response.\n */\n onError: (error: unknown) => void\n}\n\n/**\n * @returns {Promise} Indicates whether the request has been handled.\n */\nexport async function handleRequest(\n options: HandleRequestOptions\n): Promise {\n const handleResponse = async (response: Response | Error) => {\n if (response instanceof Error) {\n options.onError(response)\n }\n\n // Handle \"Response.error()\" instances.\n else if (isResponseError(response)) {\n options.onRequestError(response)\n } else {\n await options.onResponse(response)\n }\n\n return true\n }\n\n const handleResponseError = async (error: unknown): Promise => {\n // Forward the special interceptor error instances\n // to the developer. These must not be handled in any way.\n if (error instanceof InterceptorError) {\n throw result.error\n }\n\n // Support mocking Node.js-like errors.\n if (isNodeLikeError(error)) {\n options.onError(error)\n return true\n }\n\n // Handle thrown responses.\n if (error instanceof Response) {\n return await handleResponse(error)\n }\n\n return false\n }\n\n // Add the last \"request\" listener to check if the request\n // has been handled in any way. If it hasn't, resolve the\n // response promise with undefined.\n options.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== options.requestId) {\n return\n }\n\n if (options.controller[kResponsePromise].state === 'pending') {\n options.controller[kResponsePromise].resolve(undefined)\n }\n })\n\n const requestAbortPromise = new DeferredPromise()\n\n /**\n * @note `signal` is not always defined in React Native.\n */\n if (options.request.signal) {\n if (options.request.signal.aborted) {\n requestAbortPromise.reject(options.request.signal.reason)\n } else {\n options.request.signal.addEventListener(\n 'abort',\n () => {\n requestAbortPromise.reject(options.request.signal.reason)\n },\n { once: true }\n )\n }\n }\n\n const result = await until(async () => {\n // Emit the \"request\" event and wait until all the listeners\n // for that event are finished (e.g. async listeners awaited).\n // By the end of this promise, the developer cannot affect the\n // request anymore.\n const requestListtenersPromise = emitAsync(options.emitter, 'request', {\n requestId: options.requestId,\n request: options.request,\n controller: options.controller,\n })\n\n await Promise.race([\n // Short-circuit the request handling promise if the request gets aborted.\n requestAbortPromise,\n requestListtenersPromise,\n options.controller[kResponsePromise],\n ])\n\n // The response promise will settle immediately once\n // the developer calls either \"respondWith\" or \"errorWith\".\n const mockedResponse = await options.controller[kResponsePromise]\n return mockedResponse\n })\n\n // Handle the request being aborted while waiting for the request listeners.\n if (requestAbortPromise.state === 'rejected') {\n options.onError(requestAbortPromise.rejectionReason)\n return true\n }\n\n if (result.error) {\n // Handle the error during the request listener execution.\n // These can be thrown responses or request errors.\n if (await handleResponseError(result.error)) {\n return true\n }\n\n // If the developer has added \"unhandledException\" listeners,\n // allow them to handle the error. They can translate it to a\n // mocked response, network error, or forward it as-is.\n if (options.emitter.listenerCount('unhandledException') > 0) {\n // Create a new request controller just for the unhandled exception case.\n // This is needed because the original controller might have been already\n // interacted with (e.g. \"respondWith\" or \"errorWith\" called on it).\n const unhandledExceptionController = new RequestController(\n options.request\n )\n\n await emitAsync(options.emitter, 'unhandledException', {\n error: result.error,\n request: options.request,\n requestId: options.requestId,\n controller: unhandledExceptionController,\n }).then(() => {\n // If all the \"unhandledException\" listeners have finished\n // but have not handled the response in any way, preemptively\n // resolve the pending response promise from the new controller.\n // This prevents it from hanging forever.\n if (\n unhandledExceptionController[kResponsePromise].state === 'pending'\n ) {\n unhandledExceptionController[kResponsePromise].resolve(undefined)\n }\n })\n\n const nextResult = await until(\n () => unhandledExceptionController[kResponsePromise]\n )\n\n /**\n * @note Handle the result of the unhandled controller\n * in the same way as the original request controller.\n * The exception here is that thrown errors within the\n * \"unhandledException\" event do NOT result in another\n * emit of the same event. They are forwarded as-is.\n */\n if (nextResult.error) {\n return handleResponseError(nextResult.error)\n }\n\n if (nextResult.data) {\n return handleResponse(nextResult.data)\n }\n }\n\n // Otherwise, coerce unhandled exceptions to a 500 Internal Server Error response.\n options.onResponse(createServerErrorResponse(result.error))\n return true\n }\n\n /**\n * Handle a mocked Response instance.\n * @note That this can also be an Error in case\n * the developer called \"errorWith\". This differentiates\n * unhandled exceptions from intended errors.\n */\n if (result.data) {\n return handleResponse(result.data)\n }\n\n // In all other cases, consider the request unhandled.\n // The interceptor must perform it as-is.\n return false\n}\n","/**\n * A function that validates if property access is possible on an object\n * without throwing. It returns `true` if the property access is possible\n * and `false` otherwise.\n *\n * Environments like miniflare will throw on property access on certain objects\n * like Request and Response, for unimplemented properties.\n */\nexport function isPropertyAccessible>(\n obj: Obj,\n key: keyof Obj\n) {\n try {\n obj[key]\n return true\n } catch {\n return false\n }\n}\n","import { isPropertyAccessible } from './isPropertyAccessible'\n\n/**\n * Creates a generic 500 Unhandled Exception response.\n */\nexport function createServerErrorResponse(body: unknown): Response {\n return new Response(\n JSON.stringify(\n body instanceof Error\n ? {\n name: body.name,\n message: body.message,\n stack: body.stack,\n }\n : body\n ),\n {\n status: 500,\n statusText: 'Unhandled Exception',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n}\n\nexport type ResponseError = Response & { type: 'error' }\n\n/**\n * Check if the given response is a `Response.error()`.\n *\n * @note Some environments, like Miniflare (Cloudflare) do not\n * implement the \"Response.type\" property and throw on its access.\n * Safely check if we can access \"type\" on \"Response\" before continuing.\n * @see https://github.com/mswjs/msw/issues/1834\n */\nexport function isResponseError(response: Response): response is ResponseError {\n return isPropertyAccessible(response, 'type') && response.type === 'error'\n}\n","export function isNodeLikeError(\n error: unknown\n): error is NodeJS.ErrnoException {\n if (error == null) {\n return false\n }\n\n if (!(error instanceof Error)) {\n return false\n }\n\n return 'code' in error && 'errno' in error\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;;;ACDzB,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YAAY,SAAkB;AAC5B,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,WAAO,eAAe,MAAM,iBAAiB,SAAS;AAAA,EACxD;AACF;;;ADFA,IAAM,kBAAkB,OAAO,iBAAiB;AACzC,IAAM,mBAAmB,OAAO,kBAAkB;AAElD,IAAM,oBAAN,MAAwB;AAAA,EAgB7B,YAAoB,SAAkB;AAAlB;AAClB,SAAK,eAAe,IAAI;AACxB,SAAK,gBAAgB,IAAI,IAAI,gBAAgB;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,YAAY,UAA0B;AAC3C,cAAU;AAAA,MACR;AAAA,MACA,CAAC,KAAK,eAAe;AAAA,MACrB;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAEA,SAAK,eAAe,IAAI;AACxB,SAAK,gBAAgB,EAAE,QAAQ,QAAQ;AAAA,EASzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,UAAU,OAAqB;AACpC,cAAU;AAAA,MACR;AAAA,MACA,CAAC,KAAK,eAAe;AAAA,MACrB;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,KAAK,QAAQ;AAAA,IACf;AAEA,SAAK,eAAe,IAAI;AAOxB,SAAK,gBAAgB,EAAE,QAAQ,KAAK;AAAA,EACtC;AACF;AAjEG,kBAMA;;;AEdH,eAAsB,UAIpB,SACA,cACG,MACY;AACf,QAAM,WAAW,QAAQ,UAAU,SAAS;AAE5C,MAAI,SAAS,WAAW,GAAG;AACzB;AAAA,EACF;AAEA,aAAW,YAAY,UAAU;AAC/B,UAAM,SAAS,MAAM,SAAS,IAAI;AAAA,EACpC;AACF;;;ACvBA,SAAS,mBAAAA,wBAAuB;AAChC,SAAS,aAAa;;;ACMf,SAAS,qBACd,KACA,KACA;AACA,MAAI;AACF,QAAI,GAAG;AACP,WAAO;AAAA,EACT,SAAQ,GAAN;AACA,WAAO;AAAA,EACT;AACF;;;ACbO,SAAS,0BAA0B,MAAyB;AACjE,SAAO,IAAI;AAAA,IACT,KAAK;AAAA,MACH,gBAAgB,QACZ;AAAA,QACE,MAAM,KAAK;AAAA,QACX,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,MACd,IACA;AAAA,IACN;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AACF;AAYO,SAAS,gBAAgB,UAA+C;AAC7E,SAAO,qBAAqB,UAAU,MAAM,KAAK,SAAS,SAAS;AACrE;;;ACtCO,SAAS,gBACd,OACgC;AAChC,MAAI,SAAS,MAAM;AACjB,WAAO;AAAA,EACT;AAEA,MAAI,EAAE,iBAAiB,QAAQ;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO,UAAU,SAAS,WAAW;AACvC;;;AH8BA,eAAsB,cACpB,SACkB;AAClB,QAAM,iBAAiB,OAAO,aAA+B;AAC3D,QAAI,oBAAoB,OAAO;AAC7B,cAAQ,QAAQ,QAAQ;AAAA,IAC1B,WAGS,gBAAgB,QAAQ,GAAG;AAClC,cAAQ,eAAe,QAAQ;AAAA,IACjC,OAAO;AACL,YAAM,QAAQ,WAAW,QAAQ;AAAA,IACnC;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,sBAAsB,OAAO,UAAqC;AAGtE,QAAI,iBAAiB,kBAAkB;AACrC,YAAM,OAAO;AAAA,IACf;AAGA,QAAI,gBAAgB,KAAK,GAAG;AAC1B,cAAQ,QAAQ,KAAK;AACrB,aAAO;AAAA,IACT;AAGA,QAAI,iBAAiB,UAAU;AAC7B,aAAO,MAAM,eAAe,KAAK;AAAA,IACnC;AAEA,WAAO;AAAA,EACT;AAKA,UAAQ,QAAQ,KAAK,WAAW,CAAC,EAAE,WAAW,iBAAiB,MAAM;AACnE,QAAI,qBAAqB,QAAQ,WAAW;AAC1C;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,gBAAgB,EAAE,UAAU,WAAW;AAC5D,cAAQ,WAAW,gBAAgB,EAAE,QAAQ,MAAS;AAAA,IACxD;AAAA,EACF,CAAC;AAED,QAAM,sBAAsB,IAAIC,iBAA+B;AAK/D,MAAI,QAAQ,QAAQ,QAAQ;AAC1B,QAAI,QAAQ,QAAQ,OAAO,SAAS;AAClC,0BAAoB,OAAO,QAAQ,QAAQ,OAAO,MAAM;AAAA,IAC1D,OAAO;AACL,cAAQ,QAAQ,OAAO;AAAA,QACrB;AAAA,QACA,MAAM;AACJ,8BAAoB,OAAO,QAAQ,QAAQ,OAAO,MAAM;AAAA,QAC1D;AAAA,QACA,EAAE,MAAM,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,MAAM,YAAY;AAKrC,UAAM,2BAA2B,UAAU,QAAQ,SAAS,WAAW;AAAA,MACrE,WAAW,QAAQ;AAAA,MACnB,SAAS,QAAQ;AAAA,MACjB,YAAY,QAAQ;AAAA,IACtB,CAAC;AAED,UAAM,QAAQ,KAAK;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA,QAAQ,WAAW,gBAAgB;AAAA,IACrC,CAAC;AAID,UAAM,iBAAiB,MAAM,QAAQ,WAAW,gBAAgB;AAChE,WAAO;AAAA,EACT,CAAC;AAGD,MAAI,oBAAoB,UAAU,YAAY;AAC5C,YAAQ,QAAQ,oBAAoB,eAAe;AACnD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,OAAO;AAGhB,QAAI,MAAM,oBAAoB,OAAO,KAAK,GAAG;AAC3C,aAAO;AAAA,IACT;AAKA,QAAI,QAAQ,QAAQ,cAAc,oBAAoB,IAAI,GAAG;AAI3D,YAAM,+BAA+B,IAAI;AAAA,QACvC,QAAQ;AAAA,MACV;AAEA,YAAM,UAAU,QAAQ,SAAS,sBAAsB;AAAA,QACrD,OAAO,OAAO;AAAA,QACd,SAAS,QAAQ;AAAA,QACjB,WAAW,QAAQ;AAAA,QACnB,YAAY;AAAA,MACd,CAAC,EAAE,KAAK,MAAM;AAKZ,YACE,6BAA6B,gBAAgB,EAAE,UAAU,WACzD;AACA,uCAA6B,gBAAgB,EAAE,QAAQ,MAAS;AAAA,QAClE;AAAA,MACF,CAAC;AAED,YAAM,aAAa,MAAM;AAAA,QACvB,MAAM,6BAA6B,gBAAgB;AAAA,MACrD;AASA,UAAI,WAAW,OAAO;AACpB,eAAO,oBAAoB,WAAW,KAAK;AAAA,MAC7C;AAEA,UAAI,WAAW,MAAM;AACnB,eAAO,eAAe,WAAW,IAAI;AAAA,MACvC;AAAA,IACF;AAGA,YAAQ,WAAW,0BAA0B,OAAO,KAAK,CAAC;AAC1D,WAAO;AAAA,EACT;AAQA,MAAI,OAAO,MAAM;AACf,WAAO,eAAe,OAAO,IAAI;AAAA,EACnC;AAIA,SAAO;AACT;","names":["DeferredPromise","DeferredPromise"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-LK6DILFK.js b/node_modules/@mswjs/interceptors/lib/browser/chunk-LK6DILFK.js new file mode 100644 index 0000000000..f41d9eae57 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-LK6DILFK.js @@ -0,0 +1,22 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/utils/bufferUtils.ts +var encoder = new TextEncoder(); +function encodeBuffer(text) { + return encoder.encode(text); +} +function decodeBuffer(buffer, encoding) { + const decoder = new TextDecoder(encoding); + return decoder.decode(buffer); +} +function toArrayBuffer(array) { + return array.buffer.slice( + array.byteOffset, + array.byteOffset + array.byteLength + ); +} + + + + + +exports.encodeBuffer = encodeBuffer; exports.decodeBuffer = decodeBuffer; exports.toArrayBuffer = toArrayBuffer; +//# sourceMappingURL=chunk-LK6DILFK.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-LK6DILFK.js.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-LK6DILFK.js.map new file mode 100644 index 0000000000..691683680b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-LK6DILFK.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/bufferUtils.ts"],"names":[],"mappings":";AAAA,IAAM,UAAU,IAAI,YAAY;AAEzB,SAAS,aAAa,MAA0B;AACrD,SAAO,QAAQ,OAAO,IAAI;AAC5B;AAEO,SAAS,aAAa,QAAqB,UAA2B;AAC3E,QAAM,UAAU,IAAI,YAAY,QAAQ;AACxC,SAAO,QAAQ,OAAO,MAAM;AAC9B;AAOO,SAAS,cAAc,OAAgC;AAC5D,SAAO,MAAM,OAAO;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,aAAa,MAAM;AAAA,EAC3B;AACF","sourcesContent":["const encoder = new TextEncoder()\n\nexport function encodeBuffer(text: string): Uint8Array {\n return encoder.encode(text)\n}\n\nexport function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string {\n const decoder = new TextDecoder(encoding)\n return decoder.decode(buffer)\n}\n\n/**\n * Create an `ArrayBuffer` from the given `Uint8Array`.\n * Takes the byte offset into account to produce the right buffer\n * in the case when the buffer is bigger than the data view.\n */\nexport function toArrayBuffer(array: Uint8Array): ArrayBuffer {\n return array.buffer.slice(\n array.byteOffset,\n array.byteOffset + array.byteLength\n )\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-PFGO5BSM.js b/node_modules/@mswjs/interceptors/lib/browser/chunk-PFGO5BSM.js new file mode 100644 index 0000000000..3206fc0cb7 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-PFGO5BSM.js @@ -0,0 +1,25 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/utils/hasConfigurableGlobal.ts +function hasConfigurableGlobal(propertyName) { + const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName); + if (typeof descriptor === "undefined") { + return false; + } + if (typeof descriptor.get === "function" && typeof descriptor.get() === "undefined") { + return false; + } + if (typeof descriptor.get === "undefined" && descriptor.value == null) { + return false; + } + if (typeof descriptor.set === "undefined" && !descriptor.configurable) { + console.error( + `[MSW] Failed to apply interceptor: the global \`${propertyName}\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.` + ); + return false; + } + return true; +} + + + +exports.hasConfigurableGlobal = hasConfigurableGlobal; +//# sourceMappingURL=chunk-PFGO5BSM.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-PFGO5BSM.js.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-PFGO5BSM.js.map new file mode 100644 index 0000000000..4069b5ab7b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-PFGO5BSM.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/hasConfigurableGlobal.ts"],"names":[],"mappings":";AAIO,SAAS,sBAAsB,cAA+B;AACnE,QAAM,aAAa,OAAO,yBAAyB,YAAY,YAAY;AAG3E,MAAI,OAAO,eAAe,aAAa;AACrC,WAAO;AAAA,EACT;AAGA,MACE,OAAO,WAAW,QAAQ,cAC1B,OAAO,WAAW,IAAI,MAAM,aAC5B;AACA,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,WAAW,QAAQ,eAAe,WAAW,SAAS,MAAM;AACrE,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,QAAQ,eAAe,CAAC,WAAW,cAAc;AACrE,YAAQ;AAAA,MACN,mDAAmD;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT","sourcesContent":["/**\n * Returns a boolean indicating whether the given global property\n * is defined and is configurable.\n */\nexport function hasConfigurableGlobal(propertyName: string): boolean {\n const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName)\n\n // The property is not set at all.\n if (typeof descriptor === 'undefined') {\n return false\n }\n\n // The property is set to a getter that returns undefined.\n if (\n typeof descriptor.get === 'function' &&\n typeof descriptor.get() === 'undefined'\n ) {\n return false\n }\n\n // The property is set to a value equal to undefined.\n if (typeof descriptor.get === 'undefined' && descriptor.value == null) {\n return false\n }\n\n if (typeof descriptor.set === 'undefined' && !descriptor.configurable) {\n console.error(\n `[MSW] Failed to apply interceptor: the global \\`${propertyName}\\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.`\n )\n return false\n }\n\n return true\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs b/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs new file mode 100644 index 0000000000..f71287cc2b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs @@ -0,0 +1,169 @@ +// src/Interceptor.ts +import { Logger } from "@open-draft/logger"; +import { Emitter } from "strict-event-emitter"; +var INTERNAL_REQUEST_ID_HEADER_NAME = "x-interceptors-internal-request-id"; +function getGlobalSymbol(symbol) { + return ( + // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587 + globalThis[symbol] || void 0 + ); +} +function setGlobalSymbol(symbol, value) { + globalThis[symbol] = value; +} +function deleteGlobalSymbol(symbol) { + delete globalThis[symbol]; +} +var InterceptorReadyState = /* @__PURE__ */ ((InterceptorReadyState2) => { + InterceptorReadyState2["INACTIVE"] = "INACTIVE"; + InterceptorReadyState2["APPLYING"] = "APPLYING"; + InterceptorReadyState2["APPLIED"] = "APPLIED"; + InterceptorReadyState2["DISPOSING"] = "DISPOSING"; + InterceptorReadyState2["DISPOSED"] = "DISPOSED"; + return InterceptorReadyState2; +})(InterceptorReadyState || {}); +var Interceptor = class { + constructor(symbol) { + this.symbol = symbol; + this.readyState = "INACTIVE" /* INACTIVE */; + this.emitter = new Emitter(); + this.subscriptions = []; + this.logger = new Logger(symbol.description); + this.emitter.setMaxListeners(0); + this.logger.info("constructing the interceptor..."); + } + /** + * Determine if this interceptor can be applied + * in the current environment. + */ + checkEnvironment() { + return true; + } + /** + * Apply this interceptor to the current process. + * Returns an already running interceptor instance if it's present. + */ + apply() { + const logger = this.logger.extend("apply"); + logger.info("applying the interceptor..."); + if (this.readyState === "APPLIED" /* APPLIED */) { + logger.info("intercepted already applied!"); + return; + } + const shouldApply = this.checkEnvironment(); + if (!shouldApply) { + logger.info("the interceptor cannot be applied in this environment!"); + return; + } + this.readyState = "APPLYING" /* APPLYING */; + const runningInstance = this.getInstance(); + if (runningInstance) { + logger.info("found a running instance, reusing..."); + this.on = (event, listener) => { + logger.info('proxying the "%s" listener', event); + runningInstance.emitter.addListener(event, listener); + this.subscriptions.push(() => { + runningInstance.emitter.removeListener(event, listener); + logger.info('removed proxied "%s" listener!', event); + }); + return this; + }; + this.readyState = "APPLIED" /* APPLIED */; + return; + } + logger.info("no running instance found, setting up a new instance..."); + this.setup(); + this.setInstance(); + this.readyState = "APPLIED" /* APPLIED */; + } + /** + * Setup the module augments and stubs necessary for this interceptor. + * This method is not run if there's a running interceptor instance + * to prevent instantiating an interceptor multiple times. + */ + setup() { + } + /** + * Listen to the interceptor's public events. + */ + on(event, listener) { + const logger = this.logger.extend("on"); + if (this.readyState === "DISPOSING" /* DISPOSING */ || this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot listen to events, already disposed!"); + return this; + } + logger.info('adding "%s" event listener:', event, listener); + this.emitter.on(event, listener); + return this; + } + once(event, listener) { + this.emitter.once(event, listener); + return this; + } + off(event, listener) { + this.emitter.off(event, listener); + return this; + } + removeAllListeners(event) { + this.emitter.removeAllListeners(event); + return this; + } + /** + * Disposes of any side-effects this interceptor has introduced. + */ + dispose() { + const logger = this.logger.extend("dispose"); + if (this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot dispose, already disposed!"); + return; + } + logger.info("disposing the interceptor..."); + this.readyState = "DISPOSING" /* DISPOSING */; + if (!this.getInstance()) { + logger.info("no interceptors running, skipping dispose..."); + return; + } + this.clearInstance(); + logger.info("global symbol deleted:", getGlobalSymbol(this.symbol)); + if (this.subscriptions.length > 0) { + logger.info("disposing of %d subscriptions...", this.subscriptions.length); + for (const dispose of this.subscriptions) { + dispose(); + } + this.subscriptions = []; + logger.info("disposed of all subscriptions!", this.subscriptions.length); + } + this.emitter.removeAllListeners(); + logger.info("destroyed the listener!"); + this.readyState = "DISPOSED" /* DISPOSED */; + } + getInstance() { + var _a; + const instance = getGlobalSymbol(this.symbol); + this.logger.info("retrieved global instance:", (_a = instance == null ? void 0 : instance.constructor) == null ? void 0 : _a.name); + return instance; + } + setInstance() { + setGlobalSymbol(this.symbol, this); + this.logger.info("set global instance!", this.symbol.description); + } + clearInstance() { + deleteGlobalSymbol(this.symbol); + this.logger.info("cleared global instance!", this.symbol.description); + } +}; + +// src/createRequestId.ts +function createRequestId() { + return Math.random().toString(16).slice(2); +} + +export { + INTERNAL_REQUEST_ID_HEADER_NAME, + getGlobalSymbol, + deleteGlobalSymbol, + InterceptorReadyState, + Interceptor, + createRequestId +}; +//# sourceMappingURL=chunk-QED3Q6Z2.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs.map new file mode 100644 index 0000000000..1225c8315c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-QED3Q6Z2.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/Interceptor.ts","../../src/createRequestId.ts"],"sourcesContent":["import { Logger } from '@open-draft/logger'\nimport { Emitter, Listener } from 'strict-event-emitter'\n\nexport type InterceptorEventMap = Record\nexport type InterceptorSubscription = () => void\n\n/**\n * Request header name to detect when a single request\n * is being handled by nested interceptors (XHR -> ClientRequest).\n * Obscure by design to prevent collisions with user-defined headers.\n * Ideally, come up with the Interceptor-level mechanism for this.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\nexport const INTERNAL_REQUEST_ID_HEADER_NAME =\n 'x-interceptors-internal-request-id'\n\nexport function getGlobalSymbol(symbol: Symbol): V | undefined {\n return (\n // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587\n globalThis[symbol] || undefined\n )\n}\n\nfunction setGlobalSymbol(symbol: Symbol, value: any): void {\n // @ts-ignore\n globalThis[symbol] = value\n}\n\nexport function deleteGlobalSymbol(symbol: Symbol): void {\n // @ts-ignore\n delete globalThis[symbol]\n}\n\nexport enum InterceptorReadyState {\n INACTIVE = 'INACTIVE',\n APPLYING = 'APPLYING',\n APPLIED = 'APPLIED',\n DISPOSING = 'DISPOSING',\n DISPOSED = 'DISPOSED',\n}\n\nexport type ExtractEventNames> =\n Events extends Record ? EventName : never\n\nexport class Interceptor {\n protected emitter: Emitter\n protected subscriptions: Array\n protected logger: Logger\n\n public readyState: InterceptorReadyState\n\n constructor(private readonly symbol: symbol) {\n this.readyState = InterceptorReadyState.INACTIVE\n\n this.emitter = new Emitter()\n this.subscriptions = []\n this.logger = new Logger(symbol.description!)\n\n // Do not limit the maximum number of listeners\n // so not to limit the maximum amount of parallel events emitted.\n this.emitter.setMaxListeners(0)\n\n this.logger.info('constructing the interceptor...')\n }\n\n /**\n * Determine if this interceptor can be applied\n * in the current environment.\n */\n protected checkEnvironment(): boolean {\n return true\n }\n\n /**\n * Apply this interceptor to the current process.\n * Returns an already running interceptor instance if it's present.\n */\n public apply(): void {\n const logger = this.logger.extend('apply')\n logger.info('applying the interceptor...')\n\n if (this.readyState === InterceptorReadyState.APPLIED) {\n logger.info('intercepted already applied!')\n return\n }\n\n const shouldApply = this.checkEnvironment()\n\n if (!shouldApply) {\n logger.info('the interceptor cannot be applied in this environment!')\n return\n }\n\n this.readyState = InterceptorReadyState.APPLYING\n\n // Whenever applying a new interceptor, check if it hasn't been applied already.\n // This enables to apply the same interceptor multiple times, for example from a different\n // interceptor, only proxying events but keeping the stubs in a single place.\n const runningInstance = this.getInstance()\n\n if (runningInstance) {\n logger.info('found a running instance, reusing...')\n\n // Proxy any listeners you set on this instance to the running instance.\n this.on = (event, listener) => {\n logger.info('proxying the \"%s\" listener', event)\n\n // Add listeners to the running instance so they appear\n // at the top of the event listeners list and are executed first.\n runningInstance.emitter.addListener(event, listener)\n\n // Ensure that once this interceptor instance is disposed,\n // it removes all listeners it has appended to the running interceptor instance.\n this.subscriptions.push(() => {\n runningInstance.emitter.removeListener(event, listener)\n logger.info('removed proxied \"%s\" listener!', event)\n })\n\n return this\n }\n\n this.readyState = InterceptorReadyState.APPLIED\n\n return\n }\n\n logger.info('no running instance found, setting up a new instance...')\n\n // Setup the interceptor.\n this.setup()\n\n // Store the newly applied interceptor instance globally.\n this.setInstance()\n\n this.readyState = InterceptorReadyState.APPLIED\n }\n\n /**\n * Setup the module augments and stubs necessary for this interceptor.\n * This method is not run if there's a running interceptor instance\n * to prevent instantiating an interceptor multiple times.\n */\n protected setup(): void {}\n\n /**\n * Listen to the interceptor's public events.\n */\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n const logger = this.logger.extend('on')\n\n if (\n this.readyState === InterceptorReadyState.DISPOSING ||\n this.readyState === InterceptorReadyState.DISPOSED\n ) {\n logger.info('cannot listen to events, already disposed!')\n return this\n }\n\n logger.info('adding \"%s\" event listener:', event, listener)\n\n this.emitter.on(event, listener)\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.once(event, listener)\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.off(event, listener)\n return this\n }\n\n public removeAllListeners>(\n event?: EventName\n ): this {\n this.emitter.removeAllListeners(event)\n return this\n }\n\n /**\n * Disposes of any side-effects this interceptor has introduced.\n */\n public dispose(): void {\n const logger = this.logger.extend('dispose')\n\n if (this.readyState === InterceptorReadyState.DISPOSED) {\n logger.info('cannot dispose, already disposed!')\n return\n }\n\n logger.info('disposing the interceptor...')\n this.readyState = InterceptorReadyState.DISPOSING\n\n if (!this.getInstance()) {\n logger.info('no interceptors running, skipping dispose...')\n return\n }\n\n // Delete the global symbol as soon as possible,\n // indicating that the interceptor is no longer running.\n this.clearInstance()\n\n logger.info('global symbol deleted:', getGlobalSymbol(this.symbol))\n\n if (this.subscriptions.length > 0) {\n logger.info('disposing of %d subscriptions...', this.subscriptions.length)\n\n for (const dispose of this.subscriptions) {\n dispose()\n }\n\n this.subscriptions = []\n\n logger.info('disposed of all subscriptions!', this.subscriptions.length)\n }\n\n this.emitter.removeAllListeners()\n logger.info('destroyed the listener!')\n\n this.readyState = InterceptorReadyState.DISPOSED\n }\n\n private getInstance(): this | undefined {\n const instance = getGlobalSymbol(this.symbol)\n this.logger.info('retrieved global instance:', instance?.constructor?.name)\n return instance\n }\n\n private setInstance(): void {\n setGlobalSymbol(this.symbol, this)\n this.logger.info('set global instance!', this.symbol.description)\n }\n\n private clearInstance(): void {\n deleteGlobalSymbol(this.symbol)\n this.logger.info('cleared global instance!', this.symbol.description)\n }\n}\n","/**\n * Generate a random ID string to represent a request.\n * @example\n * createRequestId()\n * // \"f774b6c9c600f\"\n */\nexport function createRequestId(): string {\n return Math.random().toString(16).slice(2)\n}\n"],"mappings":"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","names":["InterceptorReadyState"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-QVOTKFTB.js b/node_modules/@mswjs/interceptors/lib/browser/chunk-QVOTKFTB.js new file mode 100644 index 0000000000..a9677a67ef --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-QVOTKFTB.js @@ -0,0 +1,295 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + + + +var _chunkFGSEOIC4js = require('./chunk-FGSEOIC4.js'); + + + +var _chunkBC2BLJQNjs = require('./chunk-BC2BLJQN.js'); + + +var _chunkPFGO5BSMjs = require('./chunk-PFGO5BSM.js'); + + + +var _chunkTIPR373Rjs = require('./chunk-TIPR373R.js'); + +// src/interceptors/fetch/index.ts +var _outvariant = require('outvariant'); +var _deferredpromise = require('@open-draft/deferred-promise'); + +// src/utils/canParseUrl.ts +function canParseUrl(url) { + try { + new URL(url); + return true; + } catch (_error) { + return false; + } +} + +// src/interceptors/fetch/utils/createNetworkError.ts +function createNetworkError(cause) { + return Object.assign(new TypeError("Failed to fetch"), { + cause + }); +} + +// src/interceptors/fetch/utils/followRedirect.ts +var REQUEST_BODY_HEADERS = [ + "content-encoding", + "content-language", + "content-location", + "content-type", + "content-length" +]; +var kRedirectCount = Symbol("kRedirectCount"); +async function followFetchRedirect(request, response) { + if (response.status !== 303 && request.body != null) { + return Promise.reject(createNetworkError()); + } + const requestUrl = new URL(request.url); + let locationUrl; + try { + locationUrl = new URL(response.headers.get("location"), request.url); + } catch (error) { + return Promise.reject(createNetworkError(error)); + } + if (!(locationUrl.protocol === "http:" || locationUrl.protocol === "https:")) { + return Promise.reject( + createNetworkError("URL scheme must be a HTTP(S) scheme") + ); + } + if (Reflect.get(request, kRedirectCount) > 20) { + return Promise.reject(createNetworkError("redirect count exceeded")); + } + Object.defineProperty(request, kRedirectCount, { + value: (Reflect.get(request, kRedirectCount) || 0) + 1 + }); + if (request.mode === "cors" && (locationUrl.username || locationUrl.password) && !sameOrigin(requestUrl, locationUrl)) { + return Promise.reject( + createNetworkError('cross origin not allowed for request mode "cors"') + ); + } + const requestInit = {}; + if ([301, 302].includes(response.status) && request.method === "POST" || response.status === 303 && !["HEAD", "GET"].includes(request.method)) { + requestInit.method = "GET"; + requestInit.body = null; + REQUEST_BODY_HEADERS.forEach((headerName) => { + request.headers.delete(headerName); + }); + } + if (!sameOrigin(requestUrl, locationUrl)) { + request.headers.delete("authorization"); + request.headers.delete("proxy-authorization"); + request.headers.delete("cookie"); + request.headers.delete("host"); + } + requestInit.headers = request.headers; + return fetch(new Request(locationUrl, requestInit)); +} +function sameOrigin(left, right) { + if (left.origin === right.origin && left.origin === "null") { + return true; + } + if (left.protocol === right.protocol && left.hostname === right.hostname && left.port === right.port) { + return true; + } + return false; +} + +// src/interceptors/fetch/utils/brotli-decompress.browser.ts +var BrotliDecompressionStream = class extends TransformStream { + constructor() { + console.warn( + "[Interceptors]: Brotli decompression of response streams is not supported in the browser" + ); + super({ + transform(chunk, controller) { + controller.enqueue(chunk); + } + }); + } +}; + +// src/interceptors/fetch/utils/decompression.ts +var PipelineStream = class extends TransformStream { + constructor(transformStreams, ...strategies) { + super({}, ...strategies); + const readable = [super.readable, ...transformStreams].reduce( + (readable2, transform) => readable2.pipeThrough(transform) + ); + Object.defineProperty(this, "readable", { + get() { + return readable; + } + }); + } +}; +function parseContentEncoding(contentEncoding) { + return contentEncoding.toLowerCase().split(",").map((coding) => coding.trim()); +} +function createDecompressionStream(contentEncoding) { + if (contentEncoding === "") { + return null; + } + const codings = parseContentEncoding(contentEncoding); + if (codings.length === 0) { + return null; + } + const transformers = codings.reduceRight( + (transformers2, coding) => { + if (coding === "gzip" || coding === "x-gzip") { + return transformers2.concat(new DecompressionStream("gzip")); + } else if (coding === "deflate") { + return transformers2.concat(new DecompressionStream("deflate")); + } else if (coding === "br") { + return transformers2.concat(new BrotliDecompressionStream()); + } else { + transformers2.length = 0; + } + return transformers2; + }, + [] + ); + return new PipelineStream(transformers); +} +function decompressResponse(response) { + if (response.body === null) { + return null; + } + const decompressionStream = createDecompressionStream( + response.headers.get("content-encoding") || "" + ); + if (!decompressionStream) { + return null; + } + response.body.pipeTo(decompressionStream.writable); + return decompressionStream.readable; +} + +// src/interceptors/fetch/index.ts +var _FetchInterceptor = class extends _chunkTIPR373Rjs.Interceptor { + constructor() { + super(_FetchInterceptor.symbol); + } + checkEnvironment() { + return _chunkPFGO5BSMjs.hasConfigurableGlobal.call(void 0, "fetch"); + } + async setup() { + const pureFetch = globalThis.fetch; + _outvariant.invariant.call(void 0, + !pureFetch[_chunkBC2BLJQNjs.IS_PATCHED_MODULE], + 'Failed to patch the "fetch" module: already patched.' + ); + globalThis.fetch = async (input, init) => { + const requestId = _chunkTIPR373Rjs.createRequestId.call(void 0, ); + const resolvedInput = typeof input === "string" && typeof location !== "undefined" && !canParseUrl(input) ? new URL(input, location.origin) : input; + const request = new Request(resolvedInput, init); + const responsePromise = new (0, _deferredpromise.DeferredPromise)(); + const controller = new (0, _chunkFGSEOIC4js.RequestController)(request); + this.logger.info("[%s] %s", request.method, request.url); + this.logger.info("awaiting for the mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + this.emitter.listenerCount("request") + ); + const isRequestHandled = await _chunkFGSEOIC4js.handleRequest.call(void 0, { + request, + requestId, + emitter: this.emitter, + controller, + onResponse: async (rawResponse) => { + this.logger.info("received mocked response!", { + rawResponse + }); + const decompressedStream = decompressResponse(rawResponse); + const response = decompressedStream === null ? rawResponse : new (0, _chunkBC2BLJQNjs.FetchResponse)(decompressedStream, rawResponse); + _chunkBC2BLJQNjs.FetchResponse.setUrl(request.url, response); + if (_chunkBC2BLJQNjs.FetchResponse.isRedirectResponse(response.status)) { + if (request.redirect === "error") { + responsePromise.reject(createNetworkError("unexpected redirect")); + return; + } + if (request.redirect === "follow") { + followFetchRedirect(request, response).then( + (response2) => { + responsePromise.resolve(response2); + }, + (reason) => { + responsePromise.reject(reason); + } + ); + return; + } + } + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + await _chunkFGSEOIC4js.emitAsync.call(void 0, this.emitter, "response", { + // Clone the mocked response for the "response" event listener. + // This way, the listener can read the response and not lock its body + // for the actual fetch consumer. + response: response.clone(), + isMockedResponse: true, + request, + requestId + }); + } + responsePromise.resolve(response); + }, + onRequestError: (response) => { + this.logger.info("request has errored!", { response }); + responsePromise.reject(createNetworkError(response)); + }, + onError: (error) => { + this.logger.info("request has been aborted!", { error }); + responsePromise.reject(error); + } + }); + if (isRequestHandled) { + this.logger.info("request has been handled, returning mock promise..."); + return responsePromise; + } + this.logger.info( + "no mocked response received, performing request as-is..." + ); + return pureFetch(request).then(async (response) => { + this.logger.info("original fetch performed", response); + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + const responseClone = response.clone(); + await _chunkFGSEOIC4js.emitAsync.call(void 0, this.emitter, "response", { + response: responseClone, + isMockedResponse: false, + request, + requestId + }); + } + return response; + }); + }; + Object.defineProperty(globalThis.fetch, _chunkBC2BLJQNjs.IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.fetch, _chunkBC2BLJQNjs.IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.fetch = pureFetch; + this.logger.info( + 'restored native "globalThis.fetch"!', + globalThis.fetch.name + ); + }); + } +}; +var FetchInterceptor = _FetchInterceptor; +FetchInterceptor.symbol = Symbol("fetch"); + + + +exports.FetchInterceptor = FetchInterceptor; +//# sourceMappingURL=chunk-QVOTKFTB.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-QVOTKFTB.js.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-QVOTKFTB.js.map new file mode 100644 index 0000000000..07453e36c1 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-QVOTKFTB.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/fetch/index.ts","../../src/utils/canParseUrl.ts","../../src/interceptors/fetch/utils/createNetworkError.ts","../../src/interceptors/fetch/utils/followRedirect.ts","../../src/interceptors/fetch/utils/brotli-decompress.browser.ts","../../src/interceptors/fetch/utils/decompression.ts"],"names":["readable","transformers","response"],"mappings":"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","sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { RequestController } from '../../RequestController'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { handleRequest } from '../../utils/handleRequest'\nimport { canParseUrl } from '../../utils/canParseUrl'\nimport { createRequestId } from '../../createRequestId'\nimport { createNetworkError } from './utils/createNetworkError'\nimport { followFetchRedirect } from './utils/followRedirect'\nimport { decompressResponse } from './utils/decompression'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\nimport { FetchResponse } from '../../utils/fetchUtils'\n\nexport class FetchInterceptor extends Interceptor {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('fetch')\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = createRequestId()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n const responsePromise = new DeferredPromise()\n const controller = new RequestController(request)\n\n this.logger.info('[%s] %s', request.method, request.url)\n this.logger.info('awaiting for the mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n emitter: this.emitter,\n controller,\n onResponse: async (rawResponse) => {\n this.logger.info('received mocked response!', {\n rawResponse,\n })\n\n // Decompress the mocked response body, if applicable.\n const decompressedStream = decompressResponse(rawResponse)\n const response =\n decompressedStream === null\n ? rawResponse\n : new FetchResponse(decompressedStream, rawResponse)\n\n FetchResponse.setUrl(request.url, response)\n\n /**\n * Undici's handling of following redirect responses.\n * Treat the \"manual\" redirect mode as a regular mocked response.\n * This way, the client can manually follow the redirect it receives.\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173\n */\n if (FetchResponse.isRedirectResponse(response.status)) {\n // Reject the request promise if its `redirect` is set to `error`\n // and it receives a mocked redirect response.\n if (request.redirect === 'error') {\n responsePromise.reject(createNetworkError('unexpected redirect'))\n return\n }\n\n if (request.redirect === 'follow') {\n followFetchRedirect(request, response).then(\n (response) => {\n responsePromise.resolve(response)\n },\n (reason) => {\n responsePromise.reject(reason)\n }\n )\n return\n }\n }\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n // Await the response listeners to finish before resolving\n // the response promise. This ensures all your logic finishes\n // before the interceptor resolves the pending response.\n await emitAsync(this.emitter, 'response', {\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n response: response.clone(),\n isMockedResponse: true,\n request,\n requestId,\n })\n }\n\n responsePromise.resolve(response)\n },\n onRequestError: (response) => {\n this.logger.info('request has errored!', { response })\n responsePromise.reject(createNetworkError(response))\n },\n onError: (error) => {\n this.logger.info('request has been aborted!', { error })\n responsePromise.reject(error)\n },\n })\n\n if (isRequestHandled) {\n this.logger.info('request has been handled, returning mock promise...')\n return responsePromise\n }\n\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n\n return pureFetch(request).then(async (response) => {\n this.logger.info('original fetch performed', response)\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n const responseClone = response.clone()\n\n await emitAsync(this.emitter, 'response', {\n response: responseClone,\n isMockedResponse: false,\n request,\n requestId,\n })\n }\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n","export function createNetworkError(cause?: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","import { createNetworkError } from './createNetworkError'\n\nconst REQUEST_BODY_HEADERS = [\n 'content-encoding',\n 'content-language',\n 'content-location',\n 'content-type',\n 'content-length',\n]\n\nconst kRedirectCount = Symbol('kRedirectCount')\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1210\n */\nexport async function followFetchRedirect(\n request: Request,\n response: Response\n): Promise {\n if (response.status !== 303 && request.body != null) {\n return Promise.reject(createNetworkError())\n }\n\n const requestUrl = new URL(request.url)\n\n let locationUrl: URL\n try {\n // If the location is a relative URL, use the request URL as the base URL.\n locationUrl = new URL(response.headers.get('location')!, request.url) \n } catch (error) {\n return Promise.reject(createNetworkError(error))\n }\n\n if (\n !(locationUrl.protocol === 'http:' || locationUrl.protocol === 'https:')\n ) {\n return Promise.reject(\n createNetworkError('URL scheme must be a HTTP(S) scheme')\n )\n }\n\n if (Reflect.get(request, kRedirectCount) > 20) {\n return Promise.reject(createNetworkError('redirect count exceeded'))\n }\n\n Object.defineProperty(request, kRedirectCount, {\n value: (Reflect.get(request, kRedirectCount) || 0) + 1,\n })\n\n if (\n request.mode === 'cors' &&\n (locationUrl.username || locationUrl.password) &&\n !sameOrigin(requestUrl, locationUrl)\n ) {\n return Promise.reject(\n createNetworkError('cross origin not allowed for request mode \"cors\"')\n )\n }\n\n const requestInit: RequestInit = {}\n\n if (\n ([301, 302].includes(response.status) && request.method === 'POST') ||\n (response.status === 303 && !['HEAD', 'GET'].includes(request.method))\n ) {\n requestInit.method = 'GET'\n requestInit.body = null\n\n REQUEST_BODY_HEADERS.forEach((headerName) => {\n request.headers.delete(headerName)\n })\n }\n\n if (!sameOrigin(requestUrl, locationUrl)) {\n request.headers.delete('authorization')\n request.headers.delete('proxy-authorization')\n request.headers.delete('cookie')\n request.headers.delete('host')\n }\n\n /**\n * @note Undici \"safely\" extracts the request body.\n * I suspect we cannot dispatch this request again\n * since its body has been read and the stream is locked.\n */\n\n requestInit.headers = request.headers\n return fetch(new Request(locationUrl, requestInit))\n}\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/util.js#L761\n */\nfunction sameOrigin(left: URL, right: URL): boolean {\n if (left.origin === right.origin && left.origin === 'null') {\n return true\n }\n\n if (\n left.protocol === right.protocol &&\n left.hostname === right.hostname &&\n left.port === right.port\n ) {\n return true\n }\n\n return false\n}\n","export class BrotliDecompressionStream extends TransformStream {\n constructor() {\n console.warn(\n '[Interceptors]: Brotli decompression of response streams is not supported in the browser'\n )\n\n super({\n transform(chunk, controller) {\n // Keep the stream as passthrough, it does nothing.\n controller.enqueue(chunk)\n },\n })\n }\n}\n","// Import from an internal alias that resolves to different modules\n// depending on the environment. This way, we can keep the fetch interceptor\n// intact while using different strategies for Brotli decompression.\nimport { BrotliDecompressionStream } from 'internal:brotli-decompress'\n\nclass PipelineStream extends TransformStream {\n constructor(\n transformStreams: Array,\n ...strategies: Array\n ) {\n super({}, ...strategies)\n\n const readable = [super.readable as any, ...transformStreams].reduce(\n (readable, transform) => readable.pipeThrough(transform)\n )\n\n Object.defineProperty(this, 'readable', {\n get() {\n return readable\n },\n })\n }\n}\n\nexport function parseContentEncoding(contentEncoding: string): Array {\n return contentEncoding\n .toLowerCase()\n .split(',')\n .map((coding) => coding.trim())\n}\n\nfunction createDecompressionStream(\n contentEncoding: string\n): TransformStream | null {\n if (contentEncoding === '') {\n return null\n }\n\n const codings = parseContentEncoding(contentEncoding)\n\n if (codings.length === 0) {\n return null\n }\n\n const transformers = codings.reduceRight>(\n (transformers, coding) => {\n if (coding === 'gzip' || coding === 'x-gzip') {\n return transformers.concat(new DecompressionStream('gzip'))\n } else if (coding === 'deflate') {\n return transformers.concat(new DecompressionStream('deflate'))\n } else if (coding === 'br') {\n return transformers.concat(new BrotliDecompressionStream())\n } else {\n transformers.length = 0\n }\n\n return transformers\n },\n []\n )\n\n return new PipelineStream(transformers)\n}\n\nexport function decompressResponse(\n response: Response\n): ReadableStream | null {\n if (response.body === null) {\n return null\n }\n\n const decompressionStream = createDecompressionStream(\n response.headers.get('content-encoding') || ''\n )\n\n if (!decompressionStream) {\n return null\n }\n\n // Use `pipeTo` and return the decompression stream's readable\n // instead of `pipeThrough` because that will lock the original\n // response stream, making it unusable as the input to Response.\n response.body.pipeTo(decompressionStream.writable)\n return decompressionStream.readable\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-TIPR373R.js b/node_modules/@mswjs/interceptors/lib/browser/chunk-TIPR373R.js new file mode 100644 index 0000000000..17ca97fd87 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-TIPR373R.js @@ -0,0 +1,169 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/Interceptor.ts +var _logger = require('@open-draft/logger'); +var _stricteventemitter = require('strict-event-emitter'); +var INTERNAL_REQUEST_ID_HEADER_NAME = "x-interceptors-internal-request-id"; +function getGlobalSymbol(symbol) { + return ( + // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587 + globalThis[symbol] || void 0 + ); +} +function setGlobalSymbol(symbol, value) { + globalThis[symbol] = value; +} +function deleteGlobalSymbol(symbol) { + delete globalThis[symbol]; +} +var InterceptorReadyState = /* @__PURE__ */ ((InterceptorReadyState2) => { + InterceptorReadyState2["INACTIVE"] = "INACTIVE"; + InterceptorReadyState2["APPLYING"] = "APPLYING"; + InterceptorReadyState2["APPLIED"] = "APPLIED"; + InterceptorReadyState2["DISPOSING"] = "DISPOSING"; + InterceptorReadyState2["DISPOSED"] = "DISPOSED"; + return InterceptorReadyState2; +})(InterceptorReadyState || {}); +var Interceptor = class { + constructor(symbol) { + this.symbol = symbol; + this.readyState = "INACTIVE" /* INACTIVE */; + this.emitter = new (0, _stricteventemitter.Emitter)(); + this.subscriptions = []; + this.logger = new (0, _logger.Logger)(symbol.description); + this.emitter.setMaxListeners(0); + this.logger.info("constructing the interceptor..."); + } + /** + * Determine if this interceptor can be applied + * in the current environment. + */ + checkEnvironment() { + return true; + } + /** + * Apply this interceptor to the current process. + * Returns an already running interceptor instance if it's present. + */ + apply() { + const logger = this.logger.extend("apply"); + logger.info("applying the interceptor..."); + if (this.readyState === "APPLIED" /* APPLIED */) { + logger.info("intercepted already applied!"); + return; + } + const shouldApply = this.checkEnvironment(); + if (!shouldApply) { + logger.info("the interceptor cannot be applied in this environment!"); + return; + } + this.readyState = "APPLYING" /* APPLYING */; + const runningInstance = this.getInstance(); + if (runningInstance) { + logger.info("found a running instance, reusing..."); + this.on = (event, listener) => { + logger.info('proxying the "%s" listener', event); + runningInstance.emitter.addListener(event, listener); + this.subscriptions.push(() => { + runningInstance.emitter.removeListener(event, listener); + logger.info('removed proxied "%s" listener!', event); + }); + return this; + }; + this.readyState = "APPLIED" /* APPLIED */; + return; + } + logger.info("no running instance found, setting up a new instance..."); + this.setup(); + this.setInstance(); + this.readyState = "APPLIED" /* APPLIED */; + } + /** + * Setup the module augments and stubs necessary for this interceptor. + * This method is not run if there's a running interceptor instance + * to prevent instantiating an interceptor multiple times. + */ + setup() { + } + /** + * Listen to the interceptor's public events. + */ + on(event, listener) { + const logger = this.logger.extend("on"); + if (this.readyState === "DISPOSING" /* DISPOSING */ || this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot listen to events, already disposed!"); + return this; + } + logger.info('adding "%s" event listener:', event, listener); + this.emitter.on(event, listener); + return this; + } + once(event, listener) { + this.emitter.once(event, listener); + return this; + } + off(event, listener) { + this.emitter.off(event, listener); + return this; + } + removeAllListeners(event) { + this.emitter.removeAllListeners(event); + return this; + } + /** + * Disposes of any side-effects this interceptor has introduced. + */ + dispose() { + const logger = this.logger.extend("dispose"); + if (this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot dispose, already disposed!"); + return; + } + logger.info("disposing the interceptor..."); + this.readyState = "DISPOSING" /* DISPOSING */; + if (!this.getInstance()) { + logger.info("no interceptors running, skipping dispose..."); + return; + } + this.clearInstance(); + logger.info("global symbol deleted:", getGlobalSymbol(this.symbol)); + if (this.subscriptions.length > 0) { + logger.info("disposing of %d subscriptions...", this.subscriptions.length); + for (const dispose of this.subscriptions) { + dispose(); + } + this.subscriptions = []; + logger.info("disposed of all subscriptions!", this.subscriptions.length); + } + this.emitter.removeAllListeners(); + logger.info("destroyed the listener!"); + this.readyState = "DISPOSED" /* DISPOSED */; + } + getInstance() { + var _a; + const instance = getGlobalSymbol(this.symbol); + this.logger.info("retrieved global instance:", (_a = instance == null ? void 0 : instance.constructor) == null ? void 0 : _a.name); + return instance; + } + setInstance() { + setGlobalSymbol(this.symbol, this); + this.logger.info("set global instance!", this.symbol.description); + } + clearInstance() { + deleteGlobalSymbol(this.symbol); + this.logger.info("cleared global instance!", this.symbol.description); + } +}; + +// src/createRequestId.ts +function createRequestId() { + return Math.random().toString(16).slice(2); +} + + + + + + + + +exports.INTERNAL_REQUEST_ID_HEADER_NAME = INTERNAL_REQUEST_ID_HEADER_NAME; exports.getGlobalSymbol = getGlobalSymbol; exports.deleteGlobalSymbol = deleteGlobalSymbol; exports.InterceptorReadyState = InterceptorReadyState; exports.Interceptor = Interceptor; exports.createRequestId = createRequestId; +//# sourceMappingURL=chunk-TIPR373R.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-TIPR373R.js.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-TIPR373R.js.map new file mode 100644 index 0000000000..0becb9b1b4 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-TIPR373R.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/Interceptor.ts","../../src/createRequestId.ts"],"names":["InterceptorReadyState"],"mappings":"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","sourcesContent":["import { Logger } from '@open-draft/logger'\nimport { Emitter, Listener } from 'strict-event-emitter'\n\nexport type InterceptorEventMap = Record\nexport type InterceptorSubscription = () => void\n\n/**\n * Request header name to detect when a single request\n * is being handled by nested interceptors (XHR -> ClientRequest).\n * Obscure by design to prevent collisions with user-defined headers.\n * Ideally, come up with the Interceptor-level mechanism for this.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\nexport const INTERNAL_REQUEST_ID_HEADER_NAME =\n 'x-interceptors-internal-request-id'\n\nexport function getGlobalSymbol(symbol: Symbol): V | undefined {\n return (\n // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587\n globalThis[symbol] || undefined\n )\n}\n\nfunction setGlobalSymbol(symbol: Symbol, value: any): void {\n // @ts-ignore\n globalThis[symbol] = value\n}\n\nexport function deleteGlobalSymbol(symbol: Symbol): void {\n // @ts-ignore\n delete globalThis[symbol]\n}\n\nexport enum InterceptorReadyState {\n INACTIVE = 'INACTIVE',\n APPLYING = 'APPLYING',\n APPLIED = 'APPLIED',\n DISPOSING = 'DISPOSING',\n DISPOSED = 'DISPOSED',\n}\n\nexport type ExtractEventNames> =\n Events extends Record ? EventName : never\n\nexport class Interceptor {\n protected emitter: Emitter\n protected subscriptions: Array\n protected logger: Logger\n\n public readyState: InterceptorReadyState\n\n constructor(private readonly symbol: symbol) {\n this.readyState = InterceptorReadyState.INACTIVE\n\n this.emitter = new Emitter()\n this.subscriptions = []\n this.logger = new Logger(symbol.description!)\n\n // Do not limit the maximum number of listeners\n // so not to limit the maximum amount of parallel events emitted.\n this.emitter.setMaxListeners(0)\n\n this.logger.info('constructing the interceptor...')\n }\n\n /**\n * Determine if this interceptor can be applied\n * in the current environment.\n */\n protected checkEnvironment(): boolean {\n return true\n }\n\n /**\n * Apply this interceptor to the current process.\n * Returns an already running interceptor instance if it's present.\n */\n public apply(): void {\n const logger = this.logger.extend('apply')\n logger.info('applying the interceptor...')\n\n if (this.readyState === InterceptorReadyState.APPLIED) {\n logger.info('intercepted already applied!')\n return\n }\n\n const shouldApply = this.checkEnvironment()\n\n if (!shouldApply) {\n logger.info('the interceptor cannot be applied in this environment!')\n return\n }\n\n this.readyState = InterceptorReadyState.APPLYING\n\n // Whenever applying a new interceptor, check if it hasn't been applied already.\n // This enables to apply the same interceptor multiple times, for example from a different\n // interceptor, only proxying events but keeping the stubs in a single place.\n const runningInstance = this.getInstance()\n\n if (runningInstance) {\n logger.info('found a running instance, reusing...')\n\n // Proxy any listeners you set on this instance to the running instance.\n this.on = (event, listener) => {\n logger.info('proxying the \"%s\" listener', event)\n\n // Add listeners to the running instance so they appear\n // at the top of the event listeners list and are executed first.\n runningInstance.emitter.addListener(event, listener)\n\n // Ensure that once this interceptor instance is disposed,\n // it removes all listeners it has appended to the running interceptor instance.\n this.subscriptions.push(() => {\n runningInstance.emitter.removeListener(event, listener)\n logger.info('removed proxied \"%s\" listener!', event)\n })\n\n return this\n }\n\n this.readyState = InterceptorReadyState.APPLIED\n\n return\n }\n\n logger.info('no running instance found, setting up a new instance...')\n\n // Setup the interceptor.\n this.setup()\n\n // Store the newly applied interceptor instance globally.\n this.setInstance()\n\n this.readyState = InterceptorReadyState.APPLIED\n }\n\n /**\n * Setup the module augments and stubs necessary for this interceptor.\n * This method is not run if there's a running interceptor instance\n * to prevent instantiating an interceptor multiple times.\n */\n protected setup(): void {}\n\n /**\n * Listen to the interceptor's public events.\n */\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n const logger = this.logger.extend('on')\n\n if (\n this.readyState === InterceptorReadyState.DISPOSING ||\n this.readyState === InterceptorReadyState.DISPOSED\n ) {\n logger.info('cannot listen to events, already disposed!')\n return this\n }\n\n logger.info('adding \"%s\" event listener:', event, listener)\n\n this.emitter.on(event, listener)\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.once(event, listener)\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.off(event, listener)\n return this\n }\n\n public removeAllListeners>(\n event?: EventName\n ): this {\n this.emitter.removeAllListeners(event)\n return this\n }\n\n /**\n * Disposes of any side-effects this interceptor has introduced.\n */\n public dispose(): void {\n const logger = this.logger.extend('dispose')\n\n if (this.readyState === InterceptorReadyState.DISPOSED) {\n logger.info('cannot dispose, already disposed!')\n return\n }\n\n logger.info('disposing the interceptor...')\n this.readyState = InterceptorReadyState.DISPOSING\n\n if (!this.getInstance()) {\n logger.info('no interceptors running, skipping dispose...')\n return\n }\n\n // Delete the global symbol as soon as possible,\n // indicating that the interceptor is no longer running.\n this.clearInstance()\n\n logger.info('global symbol deleted:', getGlobalSymbol(this.symbol))\n\n if (this.subscriptions.length > 0) {\n logger.info('disposing of %d subscriptions...', this.subscriptions.length)\n\n for (const dispose of this.subscriptions) {\n dispose()\n }\n\n this.subscriptions = []\n\n logger.info('disposed of all subscriptions!', this.subscriptions.length)\n }\n\n this.emitter.removeAllListeners()\n logger.info('destroyed the listener!')\n\n this.readyState = InterceptorReadyState.DISPOSED\n }\n\n private getInstance(): this | undefined {\n const instance = getGlobalSymbol(this.symbol)\n this.logger.info('retrieved global instance:', instance?.constructor?.name)\n return instance\n }\n\n private setInstance(): void {\n setGlobalSymbol(this.symbol, this)\n this.logger.info('set global instance!', this.symbol.description)\n }\n\n private clearInstance(): void {\n deleteGlobalSymbol(this.symbol)\n this.logger.info('cleared global instance!', this.symbol.description)\n }\n}\n","/**\n * Generate a random ID string to represent a request.\n * @example\n * createRequestId()\n * // \"f774b6c9c600f\"\n */\nexport function createRequestId(): string {\n return Math.random().toString(16).slice(2)\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-TX5GBTFY.mjs b/node_modules/@mswjs/interceptors/lib/browser/chunk-TX5GBTFY.mjs new file mode 100644 index 0000000000..f42b2faa86 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-TX5GBTFY.mjs @@ -0,0 +1,25 @@ +// src/utils/hasConfigurableGlobal.ts +function hasConfigurableGlobal(propertyName) { + const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName); + if (typeof descriptor === "undefined") { + return false; + } + if (typeof descriptor.get === "function" && typeof descriptor.get() === "undefined") { + return false; + } + if (typeof descriptor.get === "undefined" && descriptor.value == null) { + return false; + } + if (typeof descriptor.set === "undefined" && !descriptor.configurable) { + console.error( + `[MSW] Failed to apply interceptor: the global \`${propertyName}\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.` + ); + return false; + } + return true; +} + +export { + hasConfigurableGlobal +}; +//# sourceMappingURL=chunk-TX5GBTFY.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-TX5GBTFY.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-TX5GBTFY.mjs.map new file mode 100644 index 0000000000..c5a9cb80f9 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-TX5GBTFY.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/hasConfigurableGlobal.ts"],"sourcesContent":["/**\n * Returns a boolean indicating whether the given global property\n * is defined and is configurable.\n */\nexport function hasConfigurableGlobal(propertyName: string): boolean {\n const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName)\n\n // The property is not set at all.\n if (typeof descriptor === 'undefined') {\n return false\n }\n\n // The property is set to a getter that returns undefined.\n if (\n typeof descriptor.get === 'function' &&\n typeof descriptor.get() === 'undefined'\n ) {\n return false\n }\n\n // The property is set to a value equal to undefined.\n if (typeof descriptor.get === 'undefined' && descriptor.value == null) {\n return false\n }\n\n if (typeof descriptor.set === 'undefined' && !descriptor.configurable) {\n console.error(\n `[MSW] Failed to apply interceptor: the global \\`${propertyName}\\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.`\n )\n return false\n }\n\n return true\n}\n"],"mappings":";AAIO,SAAS,sBAAsB,cAA+B;AACnE,QAAM,aAAa,OAAO,yBAAyB,YAAY,YAAY;AAG3E,MAAI,OAAO,eAAe,aAAa;AACrC,WAAO;AAAA,EACT;AAGA,MACE,OAAO,WAAW,QAAQ,cAC1B,OAAO,WAAW,IAAI,MAAM,aAC5B;AACA,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,WAAW,QAAQ,eAAe,WAAW,SAAS,MAAM;AACrE,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,QAAQ,eAAe,CAAC,WAAW,cAAc;AACrE,YAAQ;AAAA,MACN,mDAAmD;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-XTX2SIN6.mjs b/node_modules/@mswjs/interceptors/lib/browser/chunk-XTX2SIN6.mjs new file mode 100644 index 0000000000..dcaaa244ea --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-XTX2SIN6.mjs @@ -0,0 +1,295 @@ +import { + RequestController, + emitAsync, + handleRequest +} from "./chunk-H5O73WD2.mjs"; +import { + FetchResponse, + IS_PATCHED_MODULE +} from "./chunk-5UK33FSU.mjs"; +import { + hasConfigurableGlobal +} from "./chunk-TX5GBTFY.mjs"; +import { + Interceptor, + createRequestId +} from "./chunk-QED3Q6Z2.mjs"; + +// src/interceptors/fetch/index.ts +import { invariant } from "outvariant"; +import { DeferredPromise } from "@open-draft/deferred-promise"; + +// src/utils/canParseUrl.ts +function canParseUrl(url) { + try { + new URL(url); + return true; + } catch (_error) { + return false; + } +} + +// src/interceptors/fetch/utils/createNetworkError.ts +function createNetworkError(cause) { + return Object.assign(new TypeError("Failed to fetch"), { + cause + }); +} + +// src/interceptors/fetch/utils/followRedirect.ts +var REQUEST_BODY_HEADERS = [ + "content-encoding", + "content-language", + "content-location", + "content-type", + "content-length" +]; +var kRedirectCount = Symbol("kRedirectCount"); +async function followFetchRedirect(request, response) { + if (response.status !== 303 && request.body != null) { + return Promise.reject(createNetworkError()); + } + const requestUrl = new URL(request.url); + let locationUrl; + try { + locationUrl = new URL(response.headers.get("location"), request.url); + } catch (error) { + return Promise.reject(createNetworkError(error)); + } + if (!(locationUrl.protocol === "http:" || locationUrl.protocol === "https:")) { + return Promise.reject( + createNetworkError("URL scheme must be a HTTP(S) scheme") + ); + } + if (Reflect.get(request, kRedirectCount) > 20) { + return Promise.reject(createNetworkError("redirect count exceeded")); + } + Object.defineProperty(request, kRedirectCount, { + value: (Reflect.get(request, kRedirectCount) || 0) + 1 + }); + if (request.mode === "cors" && (locationUrl.username || locationUrl.password) && !sameOrigin(requestUrl, locationUrl)) { + return Promise.reject( + createNetworkError('cross origin not allowed for request mode "cors"') + ); + } + const requestInit = {}; + if ([301, 302].includes(response.status) && request.method === "POST" || response.status === 303 && !["HEAD", "GET"].includes(request.method)) { + requestInit.method = "GET"; + requestInit.body = null; + REQUEST_BODY_HEADERS.forEach((headerName) => { + request.headers.delete(headerName); + }); + } + if (!sameOrigin(requestUrl, locationUrl)) { + request.headers.delete("authorization"); + request.headers.delete("proxy-authorization"); + request.headers.delete("cookie"); + request.headers.delete("host"); + } + requestInit.headers = request.headers; + return fetch(new Request(locationUrl, requestInit)); +} +function sameOrigin(left, right) { + if (left.origin === right.origin && left.origin === "null") { + return true; + } + if (left.protocol === right.protocol && left.hostname === right.hostname && left.port === right.port) { + return true; + } + return false; +} + +// src/interceptors/fetch/utils/brotli-decompress.browser.ts +var BrotliDecompressionStream = class extends TransformStream { + constructor() { + console.warn( + "[Interceptors]: Brotli decompression of response streams is not supported in the browser" + ); + super({ + transform(chunk, controller) { + controller.enqueue(chunk); + } + }); + } +}; + +// src/interceptors/fetch/utils/decompression.ts +var PipelineStream = class extends TransformStream { + constructor(transformStreams, ...strategies) { + super({}, ...strategies); + const readable = [super.readable, ...transformStreams].reduce( + (readable2, transform) => readable2.pipeThrough(transform) + ); + Object.defineProperty(this, "readable", { + get() { + return readable; + } + }); + } +}; +function parseContentEncoding(contentEncoding) { + return contentEncoding.toLowerCase().split(",").map((coding) => coding.trim()); +} +function createDecompressionStream(contentEncoding) { + if (contentEncoding === "") { + return null; + } + const codings = parseContentEncoding(contentEncoding); + if (codings.length === 0) { + return null; + } + const transformers = codings.reduceRight( + (transformers2, coding) => { + if (coding === "gzip" || coding === "x-gzip") { + return transformers2.concat(new DecompressionStream("gzip")); + } else if (coding === "deflate") { + return transformers2.concat(new DecompressionStream("deflate")); + } else if (coding === "br") { + return transformers2.concat(new BrotliDecompressionStream()); + } else { + transformers2.length = 0; + } + return transformers2; + }, + [] + ); + return new PipelineStream(transformers); +} +function decompressResponse(response) { + if (response.body === null) { + return null; + } + const decompressionStream = createDecompressionStream( + response.headers.get("content-encoding") || "" + ); + if (!decompressionStream) { + return null; + } + response.body.pipeTo(decompressionStream.writable); + return decompressionStream.readable; +} + +// src/interceptors/fetch/index.ts +var _FetchInterceptor = class extends Interceptor { + constructor() { + super(_FetchInterceptor.symbol); + } + checkEnvironment() { + return hasConfigurableGlobal("fetch"); + } + async setup() { + const pureFetch = globalThis.fetch; + invariant( + !pureFetch[IS_PATCHED_MODULE], + 'Failed to patch the "fetch" module: already patched.' + ); + globalThis.fetch = async (input, init) => { + const requestId = createRequestId(); + const resolvedInput = typeof input === "string" && typeof location !== "undefined" && !canParseUrl(input) ? new URL(input, location.origin) : input; + const request = new Request(resolvedInput, init); + const responsePromise = new DeferredPromise(); + const controller = new RequestController(request); + this.logger.info("[%s] %s", request.method, request.url); + this.logger.info("awaiting for the mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + this.emitter.listenerCount("request") + ); + const isRequestHandled = await handleRequest({ + request, + requestId, + emitter: this.emitter, + controller, + onResponse: async (rawResponse) => { + this.logger.info("received mocked response!", { + rawResponse + }); + const decompressedStream = decompressResponse(rawResponse); + const response = decompressedStream === null ? rawResponse : new FetchResponse(decompressedStream, rawResponse); + FetchResponse.setUrl(request.url, response); + if (FetchResponse.isRedirectResponse(response.status)) { + if (request.redirect === "error") { + responsePromise.reject(createNetworkError("unexpected redirect")); + return; + } + if (request.redirect === "follow") { + followFetchRedirect(request, response).then( + (response2) => { + responsePromise.resolve(response2); + }, + (reason) => { + responsePromise.reject(reason); + } + ); + return; + } + } + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + await emitAsync(this.emitter, "response", { + // Clone the mocked response for the "response" event listener. + // This way, the listener can read the response and not lock its body + // for the actual fetch consumer. + response: response.clone(), + isMockedResponse: true, + request, + requestId + }); + } + responsePromise.resolve(response); + }, + onRequestError: (response) => { + this.logger.info("request has errored!", { response }); + responsePromise.reject(createNetworkError(response)); + }, + onError: (error) => { + this.logger.info("request has been aborted!", { error }); + responsePromise.reject(error); + } + }); + if (isRequestHandled) { + this.logger.info("request has been handled, returning mock promise..."); + return responsePromise; + } + this.logger.info( + "no mocked response received, performing request as-is..." + ); + return pureFetch(request).then(async (response) => { + this.logger.info("original fetch performed", response); + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + const responseClone = response.clone(); + await emitAsync(this.emitter, "response", { + response: responseClone, + isMockedResponse: false, + request, + requestId + }); + } + return response; + }); + }; + Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.fetch = pureFetch; + this.logger.info( + 'restored native "globalThis.fetch"!', + globalThis.fetch.name + ); + }); + } +}; +var FetchInterceptor = _FetchInterceptor; +FetchInterceptor.symbol = Symbol("fetch"); + +export { + FetchInterceptor +}; +//# sourceMappingURL=chunk-XTX2SIN6.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-XTX2SIN6.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-XTX2SIN6.mjs.map new file mode 100644 index 0000000000..31bf961168 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-XTX2SIN6.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/fetch/index.ts","../../src/utils/canParseUrl.ts","../../src/interceptors/fetch/utils/createNetworkError.ts","../../src/interceptors/fetch/utils/followRedirect.ts","../../src/interceptors/fetch/utils/brotli-decompress.browser.ts","../../src/interceptors/fetch/utils/decompression.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { RequestController } from '../../RequestController'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { handleRequest } from '../../utils/handleRequest'\nimport { canParseUrl } from '../../utils/canParseUrl'\nimport { createRequestId } from '../../createRequestId'\nimport { createNetworkError } from './utils/createNetworkError'\nimport { followFetchRedirect } from './utils/followRedirect'\nimport { decompressResponse } from './utils/decompression'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\nimport { FetchResponse } from '../../utils/fetchUtils'\n\nexport class FetchInterceptor extends Interceptor {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('fetch')\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = createRequestId()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n const responsePromise = new DeferredPromise()\n const controller = new RequestController(request)\n\n this.logger.info('[%s] %s', request.method, request.url)\n this.logger.info('awaiting for the mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n emitter: this.emitter,\n controller,\n onResponse: async (rawResponse) => {\n this.logger.info('received mocked response!', {\n rawResponse,\n })\n\n // Decompress the mocked response body, if applicable.\n const decompressedStream = decompressResponse(rawResponse)\n const response =\n decompressedStream === null\n ? rawResponse\n : new FetchResponse(decompressedStream, rawResponse)\n\n FetchResponse.setUrl(request.url, response)\n\n /**\n * Undici's handling of following redirect responses.\n * Treat the \"manual\" redirect mode as a regular mocked response.\n * This way, the client can manually follow the redirect it receives.\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173\n */\n if (FetchResponse.isRedirectResponse(response.status)) {\n // Reject the request promise if its `redirect` is set to `error`\n // and it receives a mocked redirect response.\n if (request.redirect === 'error') {\n responsePromise.reject(createNetworkError('unexpected redirect'))\n return\n }\n\n if (request.redirect === 'follow') {\n followFetchRedirect(request, response).then(\n (response) => {\n responsePromise.resolve(response)\n },\n (reason) => {\n responsePromise.reject(reason)\n }\n )\n return\n }\n }\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n // Await the response listeners to finish before resolving\n // the response promise. This ensures all your logic finishes\n // before the interceptor resolves the pending response.\n await emitAsync(this.emitter, 'response', {\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n response: response.clone(),\n isMockedResponse: true,\n request,\n requestId,\n })\n }\n\n responsePromise.resolve(response)\n },\n onRequestError: (response) => {\n this.logger.info('request has errored!', { response })\n responsePromise.reject(createNetworkError(response))\n },\n onError: (error) => {\n this.logger.info('request has been aborted!', { error })\n responsePromise.reject(error)\n },\n })\n\n if (isRequestHandled) {\n this.logger.info('request has been handled, returning mock promise...')\n return responsePromise\n }\n\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n\n return pureFetch(request).then(async (response) => {\n this.logger.info('original fetch performed', response)\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n const responseClone = response.clone()\n\n await emitAsync(this.emitter, 'response', {\n response: responseClone,\n isMockedResponse: false,\n request,\n requestId,\n })\n }\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n","export function createNetworkError(cause?: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","import { createNetworkError } from './createNetworkError'\n\nconst REQUEST_BODY_HEADERS = [\n 'content-encoding',\n 'content-language',\n 'content-location',\n 'content-type',\n 'content-length',\n]\n\nconst kRedirectCount = Symbol('kRedirectCount')\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1210\n */\nexport async function followFetchRedirect(\n request: Request,\n response: Response\n): Promise {\n if (response.status !== 303 && request.body != null) {\n return Promise.reject(createNetworkError())\n }\n\n const requestUrl = new URL(request.url)\n\n let locationUrl: URL\n try {\n // If the location is a relative URL, use the request URL as the base URL.\n locationUrl = new URL(response.headers.get('location')!, request.url) \n } catch (error) {\n return Promise.reject(createNetworkError(error))\n }\n\n if (\n !(locationUrl.protocol === 'http:' || locationUrl.protocol === 'https:')\n ) {\n return Promise.reject(\n createNetworkError('URL scheme must be a HTTP(S) scheme')\n )\n }\n\n if (Reflect.get(request, kRedirectCount) > 20) {\n return Promise.reject(createNetworkError('redirect count exceeded'))\n }\n\n Object.defineProperty(request, kRedirectCount, {\n value: (Reflect.get(request, kRedirectCount) || 0) + 1,\n })\n\n if (\n request.mode === 'cors' &&\n (locationUrl.username || locationUrl.password) &&\n !sameOrigin(requestUrl, locationUrl)\n ) {\n return Promise.reject(\n createNetworkError('cross origin not allowed for request mode \"cors\"')\n )\n }\n\n const requestInit: RequestInit = {}\n\n if (\n ([301, 302].includes(response.status) && request.method === 'POST') ||\n (response.status === 303 && !['HEAD', 'GET'].includes(request.method))\n ) {\n requestInit.method = 'GET'\n requestInit.body = null\n\n REQUEST_BODY_HEADERS.forEach((headerName) => {\n request.headers.delete(headerName)\n })\n }\n\n if (!sameOrigin(requestUrl, locationUrl)) {\n request.headers.delete('authorization')\n request.headers.delete('proxy-authorization')\n request.headers.delete('cookie')\n request.headers.delete('host')\n }\n\n /**\n * @note Undici \"safely\" extracts the request body.\n * I suspect we cannot dispatch this request again\n * since its body has been read and the stream is locked.\n */\n\n requestInit.headers = request.headers\n return fetch(new Request(locationUrl, requestInit))\n}\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/util.js#L761\n */\nfunction sameOrigin(left: URL, right: URL): boolean {\n if (left.origin === right.origin && left.origin === 'null') {\n return true\n }\n\n if (\n left.protocol === right.protocol &&\n left.hostname === right.hostname &&\n left.port === right.port\n ) {\n return true\n }\n\n return false\n}\n","export class BrotliDecompressionStream extends TransformStream {\n constructor() {\n console.warn(\n '[Interceptors]: Brotli decompression of response streams is not supported in the browser'\n )\n\n super({\n transform(chunk, controller) {\n // Keep the stream as passthrough, it does nothing.\n controller.enqueue(chunk)\n },\n })\n }\n}\n","// Import from an internal alias that resolves to different modules\n// depending on the environment. This way, we can keep the fetch interceptor\n// intact while using different strategies for Brotli decompression.\nimport { BrotliDecompressionStream } from 'internal:brotli-decompress'\n\nclass PipelineStream extends TransformStream {\n constructor(\n transformStreams: Array,\n ...strategies: Array\n ) {\n super({}, ...strategies)\n\n const readable = [super.readable as any, ...transformStreams].reduce(\n (readable, transform) => readable.pipeThrough(transform)\n )\n\n Object.defineProperty(this, 'readable', {\n get() {\n return readable\n },\n })\n }\n}\n\nexport function parseContentEncoding(contentEncoding: string): Array {\n return contentEncoding\n .toLowerCase()\n .split(',')\n .map((coding) => coding.trim())\n}\n\nfunction createDecompressionStream(\n contentEncoding: string\n): TransformStream | null {\n if (contentEncoding === '') {\n return null\n }\n\n const codings = parseContentEncoding(contentEncoding)\n\n if (codings.length === 0) {\n return null\n }\n\n const transformers = codings.reduceRight>(\n (transformers, coding) => {\n if (coding === 'gzip' || coding === 'x-gzip') {\n return transformers.concat(new DecompressionStream('gzip'))\n } else if (coding === 'deflate') {\n return transformers.concat(new DecompressionStream('deflate'))\n } else if (coding === 'br') {\n return transformers.concat(new BrotliDecompressionStream())\n } else {\n transformers.length = 0\n }\n\n return transformers\n },\n []\n )\n\n return new PipelineStream(transformers)\n}\n\nexport function decompressResponse(\n response: Response\n): ReadableStream | null {\n if (response.body === null) {\n return null\n }\n\n const decompressionStream = createDecompressionStream(\n response.headers.get('content-encoding') || ''\n )\n\n if (!decompressionStream) {\n return null\n }\n\n // Use `pipeTo` and return the decompression stream's readable\n // instead of `pipeThrough` because that will lock the original\n // response stream, making it unusable as the input to Response.\n response.body.pipeTo(decompressionStream.writable)\n return decompressionStream.readable\n}\n"],"mappings":"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","names":["readable","transformers","response"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-ZIT2QX7D.js b/node_modules/@mswjs/interceptors/lib/browser/chunk-ZIT2QX7D.js new file mode 100644 index 0000000000..8a8b74e1c0 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-ZIT2QX7D.js @@ -0,0 +1,844 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + + + +var _chunkLK6DILFKjs = require('./chunk-LK6DILFK.js'); + + + +var _chunkFGSEOIC4js = require('./chunk-FGSEOIC4.js'); + + + +var _chunkBC2BLJQNjs = require('./chunk-BC2BLJQN.js'); + + +var _chunkPFGO5BSMjs = require('./chunk-PFGO5BSM.js'); + + + + +var _chunkTIPR373Rjs = require('./chunk-TIPR373R.js'); + +// src/interceptors/XMLHttpRequest/index.ts +var _outvariant = require('outvariant'); + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts + +var _isnodeprocess = require('is-node-process'); + +// src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +function concatArrayBuffer(left, right) { + const result = new Uint8Array(left.byteLength + right.byteLength); + result.set(left, 0); + result.set(right, left.byteLength); + return result; +} + +// src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +var EventPolyfill = class { + constructor(type, options) { + this.NONE = 0; + this.CAPTURING_PHASE = 1; + this.AT_TARGET = 2; + this.BUBBLING_PHASE = 3; + this.type = ""; + this.srcElement = null; + this.currentTarget = null; + this.eventPhase = 0; + this.isTrusted = true; + this.composed = false; + this.cancelable = true; + this.defaultPrevented = false; + this.bubbles = true; + this.lengthComputable = true; + this.loaded = 0; + this.total = 0; + this.cancelBubble = false; + this.returnValue = true; + this.type = type; + this.target = (options == null ? void 0 : options.target) || null; + this.currentTarget = (options == null ? void 0 : options.currentTarget) || null; + this.timeStamp = Date.now(); + } + composedPath() { + return []; + } + initEvent(type, bubbles, cancelable) { + this.type = type; + this.bubbles = !!bubbles; + this.cancelable = !!cancelable; + } + preventDefault() { + this.defaultPrevented = true; + } + stopPropagation() { + } + stopImmediatePropagation() { + } +}; + +// src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +var ProgressEventPolyfill = class extends EventPolyfill { + constructor(type, init) { + super(type); + this.lengthComputable = (init == null ? void 0 : init.lengthComputable) || false; + this.composed = (init == null ? void 0 : init.composed) || false; + this.loaded = (init == null ? void 0 : init.loaded) || 0; + this.total = (init == null ? void 0 : init.total) || 0; + } +}; + +// src/interceptors/XMLHttpRequest/utils/createEvent.ts +var SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== "undefined"; +function createEvent(target, type, init) { + const progressEvents = [ + "error", + "progress", + "loadstart", + "loadend", + "load", + "timeout", + "abort" + ]; + const ProgressEventClass = SUPPORTS_PROGRESS_EVENT ? ProgressEvent : ProgressEventPolyfill; + const event = progressEvents.includes(type) ? new ProgressEventClass(type, { + lengthComputable: true, + loaded: (init == null ? void 0 : init.loaded) || 0, + total: (init == null ? void 0 : init.total) || 0 + }) : new EventPolyfill(type, { + target, + currentTarget: target + }); + return event; +} + +// src/utils/findPropertySource.ts +function findPropertySource(target, propertyName) { + if (!(propertyName in target)) { + return null; + } + const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName); + if (hasProperty) { + return target; + } + const prototype = Reflect.getPrototypeOf(target); + return prototype ? findPropertySource(prototype, propertyName) : null; +} + +// src/utils/createProxy.ts +function createProxy(target, options) { + const proxy = new Proxy(target, optionsToProxyHandler(options)); + return proxy; +} +function optionsToProxyHandler(options) { + const { constructorCall, methodCall, getProperty, setProperty } = options; + const handler = {}; + if (typeof constructorCall !== "undefined") { + handler.construct = function(target, args, newTarget) { + const next = Reflect.construct.bind(null, target, args, newTarget); + return constructorCall.call(newTarget, args, next); + }; + } + handler.set = function(target, propertyName, nextValue) { + const next = () => { + const propertySource = findPropertySource(target, propertyName) || target; + const ownDescriptors = Reflect.getOwnPropertyDescriptor( + propertySource, + propertyName + ); + if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") { + ownDescriptors.set.apply(target, [nextValue]); + return true; + } + return Reflect.defineProperty(propertySource, propertyName, { + writable: true, + enumerable: true, + configurable: true, + value: nextValue + }); + }; + if (typeof setProperty !== "undefined") { + return setProperty.call(target, [propertyName, nextValue], next); + } + return next(); + }; + handler.get = function(target, propertyName, receiver) { + const next = () => target[propertyName]; + const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next(); + if (typeof value === "function") { + return (...args) => { + const next2 = value.bind(target, ...args); + if (typeof methodCall !== "undefined") { + return methodCall.call(target, [propertyName, args], next2); + } + return next2(); + }; + } + return value; + }; + return handler; +} + +// src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +function isDomParserSupportedType(type) { + const supportedTypes = [ + "application/xhtml+xml", + "application/xml", + "image/svg+xml", + "text/html", + "text/xml" + ]; + return supportedTypes.some((supportedType) => { + return type.startsWith(supportedType); + }); +} + +// src/utils/parseJson.ts +function parseJson(data) { + try { + const json = JSON.parse(data); + return json; + } catch (_) { + return null; + } +} + +// src/interceptors/XMLHttpRequest/utils/createResponse.ts +function createResponse(request, body) { + const responseBodyOrNull = _chunkBC2BLJQNjs.FetchResponse.isResponseWithBody(request.status) ? body : null; + return new (0, _chunkBC2BLJQNjs.FetchResponse)(responseBodyOrNull, { + url: request.responseURL, + status: request.status, + statusText: request.statusText, + headers: createHeadersFromXMLHttpReqestHeaders( + request.getAllResponseHeaders() + ) + }); +} +function createHeadersFromXMLHttpReqestHeaders(headersString) { + const headers = new Headers(); + const lines = headersString.split(/[\r\n]+/); + for (const line of lines) { + if (line.trim() === "") { + continue; + } + const [name, ...parts] = line.split(": "); + const value = parts.join(": "); + headers.append(name, value); + } + return headers; +} + +// src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +async function getBodyByteLength(input) { + const explicitContentLength = input.headers.get("content-length"); + if (explicitContentLength != null && explicitContentLength !== "") { + return Number(explicitContentLength); + } + const buffer = await input.arrayBuffer(); + return buffer.byteLength; +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +var kIsRequestHandled = Symbol("kIsRequestHandled"); +var IS_NODE = _isnodeprocess.isNodeProcess.call(void 0, ); +var kFetchRequest = Symbol("kFetchRequest"); +var XMLHttpRequestController = class { + constructor(initialRequest, logger) { + this.initialRequest = initialRequest; + this.logger = logger; + this.method = "GET"; + this.url = null; + this[kIsRequestHandled] = false; + this.events = /* @__PURE__ */ new Map(); + this.uploadEvents = /* @__PURE__ */ new Map(); + this.requestId = _chunkTIPR373Rjs.createRequestId.call(void 0, ); + this.requestHeaders = new Headers(); + this.responseBuffer = new Uint8Array(); + this.request = createProxy(initialRequest, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "ontimeout": { + const eventName = propertyName.slice( + 2 + ); + this.request.addEventListener(eventName, nextValue); + return invoke(); + } + default: { + return invoke(); + } + } + }, + methodCall: ([methodName, args], invoke) => { + var _a; + switch (methodName) { + case "open": { + const [method, url] = args; + if (typeof url === "undefined") { + this.method = "GET"; + this.url = toAbsoluteUrl(method); + } else { + this.method = method; + this.url = toAbsoluteUrl(url); + } + this.logger = this.logger.extend(`${this.method} ${this.url.href}`); + this.logger.info("open", this.method, this.url.href); + return invoke(); + } + case "addEventListener": { + const [eventName, listener] = args; + this.registerEvent(eventName, listener); + this.logger.info("addEventListener", eventName, listener); + return invoke(); + } + case "setRequestHeader": { + const [name, value] = args; + this.requestHeaders.set(name, value); + this.logger.info("setRequestHeader", name, value); + return invoke(); + } + case "send": { + const [body] = args; + this.request.addEventListener("load", () => { + if (typeof this.onResponse !== "undefined") { + const fetchResponse = createResponse( + this.request, + /** + * The `response` property is the right way to read + * the ambiguous response body, as the request's "responseType" may differ. + * @see https://xhr.spec.whatwg.org/#the-response-attribute + */ + this.request.response + ); + this.onResponse.call(this, { + response: fetchResponse, + isMockedResponse: this[kIsRequestHandled], + request: fetchRequest, + requestId: this.requestId + }); + } + }); + const requestBody = typeof body === "string" ? _chunkLK6DILFKjs.encodeBuffer.call(void 0, body) : body; + const fetchRequest = this.toFetchApiRequest(requestBody); + this[kFetchRequest] = fetchRequest.clone(); + const onceRequestSettled = ((_a = this.onRequest) == null ? void 0 : _a.call(this, { + request: fetchRequest, + requestId: this.requestId + })) || Promise.resolve(); + onceRequestSettled.finally(() => { + if (!this[kIsRequestHandled]) { + this.logger.info( + "request callback settled but request has not been handled (readystate %d), performing as-is...", + this.request.readyState + ); + if (IS_NODE) { + this.request.setRequestHeader( + _chunkTIPR373Rjs.INTERNAL_REQUEST_ID_HEADER_NAME, + this.requestId + ); + } + return invoke(); + } + }); + break; + } + default: { + return invoke(); + } + } + } + }); + define( + this.request, + "upload", + createProxy(this.request.upload, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "onloadstart": + case "onprogress": + case "onaboart": + case "onerror": + case "onload": + case "ontimeout": + case "onloadend": { + const eventName = propertyName.slice( + 2 + ); + this.registerUploadEvent(eventName, nextValue); + } + } + return invoke(); + }, + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "addEventListener": { + const [eventName, listener] = args; + this.registerUploadEvent(eventName, listener); + this.logger.info("upload.addEventListener", eventName, listener); + return invoke(); + } + } + } + }) + ); + } + registerEvent(eventName, listener) { + const prevEvents = this.events.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.events.set(eventName, nextEvents); + this.logger.info('registered event "%s"', eventName, listener); + } + registerUploadEvent(eventName, listener) { + const prevEvents = this.uploadEvents.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.uploadEvents.set(eventName, nextEvents); + this.logger.info('registered upload event "%s"', eventName, listener); + } + /** + * Responds to the current request with the given + * Fetch API `Response` instance. + */ + async respondWith(response) { + this[kIsRequestHandled] = true; + if (this[kFetchRequest]) { + const totalRequestBodyLength = await getBodyByteLength( + this[kFetchRequest] + ); + this.trigger("loadstart", this.request.upload, { + loaded: 0, + total: totalRequestBodyLength + }); + this.trigger("progress", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("load", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("loadend", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + } + this.logger.info( + "responding with a mocked response: %d %s", + response.status, + response.statusText + ); + define(this.request, "status", response.status); + define(this.request, "statusText", response.statusText); + define(this.request, "responseURL", this.url.href); + this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, { + apply: (_, __, args) => { + this.logger.info("getResponseHeader", args[0]); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning null"); + return null; + } + const headerValue = response.headers.get(args[0]); + this.logger.info( + 'resolved response header "%s" to', + args[0], + headerValue + ); + return headerValue; + } + }); + this.request.getAllResponseHeaders = new Proxy( + this.request.getAllResponseHeaders, + { + apply: () => { + this.logger.info("getAllResponseHeaders"); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning empty string"); + return ""; + } + const headersList = Array.from(response.headers.entries()); + const allHeaders = headersList.map(([headerName, headerValue]) => { + return `${headerName}: ${headerValue}`; + }).join("\r\n"); + this.logger.info("resolved all response headers to", allHeaders); + return allHeaders; + } + } + ); + Object.defineProperties(this.request, { + response: { + enumerable: true, + configurable: false, + get: () => this.response + }, + responseText: { + enumerable: true, + configurable: false, + get: () => this.responseText + }, + responseXML: { + enumerable: true, + configurable: false, + get: () => this.responseXML + } + }); + const totalResponseBodyLength = await getBodyByteLength(response.clone()); + this.logger.info("calculated response body length", totalResponseBodyLength); + this.trigger("loadstart", this.request, { + loaded: 0, + total: totalResponseBodyLength + }); + this.setReadyState(this.request.HEADERS_RECEIVED); + this.setReadyState(this.request.LOADING); + const finalizeResponse = () => { + this.logger.info("finalizing the mocked response..."); + this.setReadyState(this.request.DONE); + this.trigger("load", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + this.trigger("loadend", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + }; + if (response.body) { + this.logger.info("mocked response has body, streaming..."); + const reader = response.body.getReader(); + const readNextResponseBodyChunk = async () => { + const { value, done } = await reader.read(); + if (done) { + this.logger.info("response body stream done!"); + finalizeResponse(); + return; + } + if (value) { + this.logger.info("read response body chunk:", value); + this.responseBuffer = concatArrayBuffer(this.responseBuffer, value); + this.trigger("progress", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + } + readNextResponseBodyChunk(); + }; + readNextResponseBodyChunk(); + } else { + finalizeResponse(); + } + } + responseBufferToText() { + return _chunkLK6DILFKjs.decodeBuffer.call(void 0, this.responseBuffer); + } + get response() { + this.logger.info( + "getResponse (responseType: %s)", + this.request.responseType + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + switch (this.request.responseType) { + case "json": { + const responseJson = parseJson(this.responseBufferToText()); + this.logger.info("resolved response JSON", responseJson); + return responseJson; + } + case "arraybuffer": { + const arrayBuffer = _chunkLK6DILFKjs.toArrayBuffer.call(void 0, this.responseBuffer); + this.logger.info("resolved response ArrayBuffer", arrayBuffer); + return arrayBuffer; + } + case "blob": { + const mimeType = this.request.getResponseHeader("Content-Type") || "text/plain"; + const responseBlob = new Blob([this.responseBufferToText()], { + type: mimeType + }); + this.logger.info( + "resolved response Blob (mime type: %s)", + responseBlob, + mimeType + ); + return responseBlob; + } + default: { + const responseText = this.responseBufferToText(); + this.logger.info( + 'resolving "%s" response type as text', + this.request.responseType, + responseText + ); + return responseText; + } + } + } + get responseText() { + _outvariant.invariant.call(void 0, + this.request.responseType === "" || this.request.responseType === "text", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.LOADING && this.request.readyState !== this.request.DONE) { + return ""; + } + const responseText = this.responseBufferToText(); + this.logger.info('getResponseText: "%s"', responseText); + return responseText; + } + get responseXML() { + _outvariant.invariant.call(void 0, + this.request.responseType === "" || this.request.responseType === "document", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + const contentType = this.request.getResponseHeader("Content-Type") || ""; + if (typeof DOMParser === "undefined") { + console.warn( + "Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly." + ); + return null; + } + if (isDomParserSupportedType(contentType)) { + return new DOMParser().parseFromString( + this.responseBufferToText(), + contentType + ); + } + return null; + } + errorWith(error) { + this[kIsRequestHandled] = true; + this.logger.info("responding with an error"); + this.setReadyState(this.request.DONE); + this.trigger("error", this.request); + this.trigger("loadend", this.request); + } + /** + * Transitions this request's `readyState` to the given one. + */ + setReadyState(nextReadyState) { + this.logger.info( + "setReadyState: %d -> %d", + this.request.readyState, + nextReadyState + ); + if (this.request.readyState === nextReadyState) { + this.logger.info("ready state identical, skipping transition..."); + return; + } + define(this.request, "readyState", nextReadyState); + this.logger.info("set readyState to: %d", nextReadyState); + if (nextReadyState !== this.request.UNSENT) { + this.logger.info('triggerring "readystatechange" event...'); + this.trigger("readystatechange", this.request); + } + } + /** + * Triggers given event on the `XMLHttpRequest` instance. + */ + trigger(eventName, target, options) { + const callback = target[`on${eventName}`]; + const event = createEvent(target, eventName, options); + this.logger.info('trigger "%s"', eventName, options || ""); + if (typeof callback === "function") { + this.logger.info('found a direct "%s" callback, calling...', eventName); + callback.call(target, event); + } + const events = target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events; + for (const [registeredEventName, listeners] of events) { + if (registeredEventName === eventName) { + this.logger.info( + 'found %d listener(s) for "%s" event, calling...', + listeners.length, + eventName + ); + listeners.forEach((listener) => listener.call(target, event)); + } + } + } + /** + * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance. + */ + toFetchApiRequest(body) { + this.logger.info("converting request to a Fetch API Request..."); + const resolvedBody = body instanceof Document ? body.documentElement.innerText : body; + const fetchRequest = new Request(this.url.href, { + method: this.method, + headers: this.requestHeaders, + /** + * @see https://xhr.spec.whatwg.org/#cross-origin-credentials + */ + credentials: this.request.withCredentials ? "include" : "same-origin", + body: ["GET", "HEAD"].includes(this.method.toUpperCase()) ? null : resolvedBody + }); + const proxyHeaders = createProxy(fetchRequest.headers, { + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "append": + case "set": { + const [headerName, headerValue] = args; + this.request.setRequestHeader(headerName, headerValue); + break; + } + case "delete": { + const [headerName] = args; + console.warn( + `XMLHttpRequest: Cannot remove a "${headerName}" header from the Fetch API representation of the "${fetchRequest.method} ${fetchRequest.url}" request. XMLHttpRequest headers cannot be removed.` + ); + break; + } + } + return invoke(); + } + }); + define(fetchRequest, "headers", proxyHeaders); + this.logger.info("converted request to a Fetch API Request!", fetchRequest); + return fetchRequest; + } +}; +kIsRequestHandled, kFetchRequest; +function toAbsoluteUrl(url) { + if (typeof location === "undefined") { + return new URL(url); + } + return new URL(url.toString(), location.href); +} +function define(target, property, value) { + Reflect.defineProperty(target, property, { + // Ensure writable properties to allow redefining readonly properties. + writable: true, + enumerable: true, + value + }); +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +function createXMLHttpRequestProxy({ + emitter, + logger +}) { + const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, { + construct(target, args, newTarget) { + logger.info("constructed new XMLHttpRequest"); + const originalRequest = Reflect.construct( + target, + args, + newTarget + ); + const prototypeDescriptors = Object.getOwnPropertyDescriptors( + target.prototype + ); + for (const propertyName in prototypeDescriptors) { + Reflect.defineProperty( + originalRequest, + propertyName, + prototypeDescriptors[propertyName] + ); + } + const xhrRequestController = new XMLHttpRequestController( + originalRequest, + logger + ); + xhrRequestController.onRequest = async function({ request, requestId }) { + const controller = new (0, _chunkFGSEOIC4js.RequestController)(request); + this.logger.info("awaiting mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + emitter.listenerCount("request") + ); + const isRequestHandled = await _chunkFGSEOIC4js.handleRequest.call(void 0, { + request, + requestId, + controller, + emitter, + onResponse: async (response) => { + await this.respondWith(response); + }, + onRequestError: () => { + this.errorWith(new TypeError("Network error")); + }, + onError: (error) => { + this.logger.info("request errored!", { error }); + if (error instanceof Error) { + this.errorWith(error); + } + } + }); + if (!isRequestHandled) { + this.logger.info( + "no mocked response received, performing request as-is..." + ); + } + }; + xhrRequestController.onResponse = async function({ + response, + isMockedResponse, + request, + requestId + }) { + this.logger.info( + 'emitting the "response" event for %s listener(s)...', + emitter.listenerCount("response") + ); + emitter.emit("response", { + response, + isMockedResponse, + request, + requestId + }); + }; + return xhrRequestController.request; + } + }); + return XMLHttpRequestProxy; +} + +// src/interceptors/XMLHttpRequest/index.ts +var _XMLHttpRequestInterceptor = class extends _chunkTIPR373Rjs.Interceptor { + constructor() { + super(_XMLHttpRequestInterceptor.interceptorSymbol); + } + checkEnvironment() { + return _chunkPFGO5BSMjs.hasConfigurableGlobal.call(void 0, "XMLHttpRequest"); + } + setup() { + const logger = this.logger.extend("setup"); + logger.info('patching "XMLHttpRequest" module...'); + const PureXMLHttpRequest = globalThis.XMLHttpRequest; + _outvariant.invariant.call(void 0, + !PureXMLHttpRequest[_chunkBC2BLJQNjs.IS_PATCHED_MODULE], + 'Failed to patch the "XMLHttpRequest" module: already patched.' + ); + globalThis.XMLHttpRequest = createXMLHttpRequestProxy({ + emitter: this.emitter, + logger: this.logger + }); + logger.info( + 'native "XMLHttpRequest" module patched!', + globalThis.XMLHttpRequest.name + ); + Object.defineProperty(globalThis.XMLHttpRequest, _chunkBC2BLJQNjs.IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.XMLHttpRequest, _chunkBC2BLJQNjs.IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.XMLHttpRequest = PureXMLHttpRequest; + logger.info( + 'native "XMLHttpRequest" module restored!', + globalThis.XMLHttpRequest.name + ); + }); + } +}; +var XMLHttpRequestInterceptor = _XMLHttpRequestInterceptor; +XMLHttpRequestInterceptor.interceptorSymbol = Symbol("xhr"); + + + +exports.XMLHttpRequestInterceptor = XMLHttpRequestInterceptor; +//# sourceMappingURL=chunk-ZIT2QX7D.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/chunk-ZIT2QX7D.js.map b/node_modules/@mswjs/interceptors/lib/browser/chunk-ZIT2QX7D.js.map new file mode 100644 index 0000000000..dcd5d0b31b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/chunk-ZIT2QX7D.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/XMLHttpRequest/index.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts","../../src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts","../../src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts","../../src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts","../../src/interceptors/XMLHttpRequest/utils/createEvent.ts","../../src/utils/findPropertySource.ts","../../src/utils/createProxy.ts","../../src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts","../../src/utils/parseJson.ts","../../src/interceptors/XMLHttpRequest/utils/createResponse.ts","../../src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts"],"names":["invariant","next"],"mappings":"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","sourcesContent":["import { invariant } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { createXMLHttpRequestProxy } from './XMLHttpRequestProxy'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\n\nexport type XMLHttpRequestEmitter = Emitter\n\nexport class XMLHttpRequestInterceptor extends Interceptor {\n static interceptorSymbol = Symbol('xhr')\n\n constructor() {\n super(XMLHttpRequestInterceptor.interceptorSymbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('XMLHttpRequest')\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('patching \"XMLHttpRequest\" module...')\n\n const PureXMLHttpRequest = globalThis.XMLHttpRequest\n\n invariant(\n !(PureXMLHttpRequest as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"XMLHttpRequest\" module: already patched.'\n )\n\n globalThis.XMLHttpRequest = createXMLHttpRequestProxy({\n emitter: this.emitter,\n logger: this.logger,\n })\n\n logger.info(\n 'native \"XMLHttpRequest\" module patched!',\n globalThis.XMLHttpRequest.name\n )\n\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.XMLHttpRequest = PureXMLHttpRequest\n logger.info(\n 'native \"XMLHttpRequest\" module restored!',\n globalThis.XMLHttpRequest.name\n )\n })\n }\n}\n","import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport type { Logger } from '@open-draft/logger'\nimport { concatArrayBuffer } from './utils/concatArrayBuffer'\nimport { createEvent } from './utils/createEvent'\nimport {\n decodeBuffer,\n encodeBuffer,\n toArrayBuffer,\n} from '../../utils/bufferUtils'\nimport { createProxy } from '../../utils/createProxy'\nimport { isDomParserSupportedType } from './utils/isDomParserSupportedType'\nimport { parseJson } from '../../utils/parseJson'\nimport { createResponse } from './utils/createResponse'\nimport { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'\nimport { createRequestId } from '../../createRequestId'\nimport { getBodyByteLength } from './utils/getBodyByteLength'\n\nconst kIsRequestHandled = Symbol('kIsRequestHandled')\nconst IS_NODE = isNodeProcess()\nconst kFetchRequest = Symbol('kFetchRequest')\n\n/**\n * An `XMLHttpRequest` instance controller that allows us\n * to handle any given request instance (e.g. responding to it).\n */\nexport class XMLHttpRequestController {\n public request: XMLHttpRequest\n public requestId: string\n public onRequest?: (\n this: XMLHttpRequestController,\n args: {\n request: Request\n requestId: string\n }\n ) => Promise\n public onResponse?: (\n this: XMLHttpRequestController,\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ) => void;\n\n [kIsRequestHandled]: boolean;\n [kFetchRequest]?: Request\n private method: string = 'GET'\n private url: URL = null as any\n private requestHeaders: Headers\n private responseBuffer: Uint8Array\n private events: Map>\n private uploadEvents: Map<\n keyof XMLHttpRequestEventTargetEventMap,\n Array\n >\n\n constructor(readonly initialRequest: XMLHttpRequest, public logger: Logger) {\n this[kIsRequestHandled] = false\n\n this.events = new Map()\n this.uploadEvents = new Map()\n this.requestId = createRequestId()\n this.requestHeaders = new Headers()\n this.responseBuffer = new Uint8Array()\n\n this.request = createProxy(initialRequest, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'ontimeout': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n /**\n * @note Proxy callbacks to event listeners because JSDOM has trouble\n * translating these properties to callbacks. It seemed to be operating\n * on events exclusively.\n */\n this.request.addEventListener(eventName, nextValue as any)\n\n return invoke()\n }\n\n default: {\n return invoke()\n }\n }\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'open': {\n const [method, url] = args as [string, string | undefined]\n\n if (typeof url === 'undefined') {\n this.method = 'GET'\n this.url = toAbsoluteUrl(method)\n } else {\n this.method = method\n this.url = toAbsoluteUrl(url)\n }\n\n this.logger = this.logger.extend(`${this.method} ${this.url.href}`)\n this.logger.info('open', this.method, this.url.href)\n\n return invoke()\n }\n\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n\n this.registerEvent(eventName, listener)\n this.logger.info('addEventListener', eventName, listener)\n\n return invoke()\n }\n\n case 'setRequestHeader': {\n const [name, value] = args as [string, string]\n this.requestHeaders.set(name, value)\n\n this.logger.info('setRequestHeader', name, value)\n\n return invoke()\n }\n\n case 'send': {\n const [body] = args as [\n body?: XMLHttpRequestBodyInit | Document | null\n ]\n\n this.request.addEventListener('load', () => {\n if (typeof this.onResponse !== 'undefined') {\n // Create a Fetch API Response representation of whichever\n // response this XMLHttpRequest received. Note those may\n // be either a mocked and the original response.\n const fetchResponse = createResponse(\n this.request,\n /**\n * The `response` property is the right way to read\n * the ambiguous response body, as the request's \"responseType\" may differ.\n * @see https://xhr.spec.whatwg.org/#the-response-attribute\n */\n this.request.response\n )\n\n // Notify the consumer about the response.\n this.onResponse.call(this, {\n response: fetchResponse,\n isMockedResponse: this[kIsRequestHandled],\n request: fetchRequest,\n requestId: this.requestId!,\n })\n }\n })\n\n const requestBody =\n typeof body === 'string' ? encodeBuffer(body) : body\n\n // Delegate request handling to the consumer.\n const fetchRequest = this.toFetchApiRequest(requestBody)\n this[kFetchRequest] = fetchRequest.clone()\n\n const onceRequestSettled =\n this.onRequest?.call(this, {\n request: fetchRequest,\n requestId: this.requestId!,\n }) || Promise.resolve()\n\n onceRequestSettled.finally(() => {\n // If the consumer didn't handle the request (called `.respondWith()`) perform it as-is.\n if (!this[kIsRequestHandled]) {\n this.logger.info(\n 'request callback settled but request has not been handled (readystate %d), performing as-is...',\n this.request.readyState\n )\n\n /**\n * @note Set the intercepted request ID on the original request in Node.js\n * so that if it triggers any other interceptors, they don't attempt\n * to process it once again.\n *\n * For instance, XMLHttpRequest is often implemented via \"http.ClientRequest\"\n * and we don't want for both XHR and ClientRequest interceptors to\n * handle the same request at the same time (e.g. emit the \"response\" event twice).\n */\n if (IS_NODE) {\n this.request.setRequestHeader(\n INTERNAL_REQUEST_ID_HEADER_NAME,\n this.requestId!\n )\n }\n\n return invoke()\n }\n })\n\n break\n }\n\n default: {\n return invoke()\n }\n }\n },\n })\n\n /**\n * Proxy the `.upload` property to gather the event listeners/callbacks.\n */\n define(\n this.request,\n 'upload',\n createProxy(this.request.upload, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'onloadstart':\n case 'onprogress':\n case 'onaboart':\n case 'onerror':\n case 'onload':\n case 'ontimeout':\n case 'onloadend': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n this.registerUploadEvent(eventName, nextValue as Function)\n }\n }\n\n return invoke()\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n this.registerUploadEvent(eventName, listener)\n this.logger.info('upload.addEventListener', eventName, listener)\n\n return invoke()\n }\n }\n },\n })\n )\n }\n\n private registerEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.events.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.events.set(eventName, nextEvents)\n\n this.logger.info('registered event \"%s\"', eventName, listener)\n }\n\n private registerUploadEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.uploadEvents.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.uploadEvents.set(eventName, nextEvents)\n\n this.logger.info('registered upload event \"%s\"', eventName, listener)\n }\n\n /**\n * Responds to the current request with the given\n * Fetch API `Response` instance.\n */\n public async respondWith(response: Response): Promise {\n /**\n * @note Since `XMLHttpRequestController` delegates the handling of the responses\n * to the \"load\" event listener that doesn't distinguish between the mocked and original\n * responses, mark the request that had a mocked response with a corresponding symbol.\n *\n * Mark this request as having a mocked response immediately since\n * calculating request/response total body length is asynchronous.\n */\n this[kIsRequestHandled] = true\n\n /**\n * Dispatch request upload events for requests with a body.\n * @see https://github.com/mswjs/interceptors/issues/573\n */\n if (this[kFetchRequest]) {\n const totalRequestBodyLength = await getBodyByteLength(\n this[kFetchRequest]\n )\n\n this.trigger('loadstart', this.request.upload, {\n loaded: 0,\n total: totalRequestBodyLength,\n })\n this.trigger('progress', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('load', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('loadend', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n }\n\n this.logger.info(\n 'responding with a mocked response: %d %s',\n response.status,\n response.statusText\n )\n\n define(this.request, 'status', response.status)\n define(this.request, 'statusText', response.statusText)\n define(this.request, 'responseURL', this.url.href)\n\n this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, {\n apply: (_, __, args: [name: string]) => {\n this.logger.info('getResponseHeader', args[0])\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning null')\n\n // Headers not received yet, nothing to return.\n return null\n }\n\n const headerValue = response.headers.get(args[0])\n this.logger.info(\n 'resolved response header \"%s\" to',\n args[0],\n headerValue\n )\n\n return headerValue\n },\n })\n\n this.request.getAllResponseHeaders = new Proxy(\n this.request.getAllResponseHeaders,\n {\n apply: () => {\n this.logger.info('getAllResponseHeaders')\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning empty string')\n\n // Headers not received yet, nothing to return.\n return ''\n }\n\n const headersList = Array.from(response.headers.entries())\n const allHeaders = headersList\n .map(([headerName, headerValue]) => {\n return `${headerName}: ${headerValue}`\n })\n .join('\\r\\n')\n\n this.logger.info('resolved all response headers to', allHeaders)\n\n return allHeaders\n },\n }\n )\n\n // Update the response getters to resolve against the mocked response.\n Object.defineProperties(this.request, {\n response: {\n enumerable: true,\n configurable: false,\n get: () => this.response,\n },\n responseText: {\n enumerable: true,\n configurable: false,\n get: () => this.responseText,\n },\n responseXML: {\n enumerable: true,\n configurable: false,\n get: () => this.responseXML,\n },\n })\n\n const totalResponseBodyLength = await getBodyByteLength(response.clone())\n\n this.logger.info('calculated response body length', totalResponseBodyLength)\n\n this.trigger('loadstart', this.request, {\n loaded: 0,\n total: totalResponseBodyLength,\n })\n\n this.setReadyState(this.request.HEADERS_RECEIVED)\n this.setReadyState(this.request.LOADING)\n\n const finalizeResponse = () => {\n this.logger.info('finalizing the mocked response...')\n\n this.setReadyState(this.request.DONE)\n\n this.trigger('load', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n\n this.trigger('loadend', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n if (response.body) {\n this.logger.info('mocked response has body, streaming...')\n\n const reader = response.body.getReader()\n\n const readNextResponseBodyChunk = async () => {\n const { value, done } = await reader.read()\n\n if (done) {\n this.logger.info('response body stream done!')\n finalizeResponse()\n return\n }\n\n if (value) {\n this.logger.info('read response body chunk:', value)\n this.responseBuffer = concatArrayBuffer(this.responseBuffer, value)\n\n this.trigger('progress', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n readNextResponseBodyChunk()\n }\n\n readNextResponseBodyChunk()\n } else {\n finalizeResponse()\n }\n }\n\n private responseBufferToText(): string {\n return decodeBuffer(this.responseBuffer)\n }\n\n get response(): unknown {\n this.logger.info(\n 'getResponse (responseType: %s)',\n this.request.responseType\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n switch (this.request.responseType) {\n case 'json': {\n const responseJson = parseJson(this.responseBufferToText())\n this.logger.info('resolved response JSON', responseJson)\n\n return responseJson\n }\n\n case 'arraybuffer': {\n const arrayBuffer = toArrayBuffer(this.responseBuffer)\n this.logger.info('resolved response ArrayBuffer', arrayBuffer)\n\n return arrayBuffer\n }\n\n case 'blob': {\n const mimeType =\n this.request.getResponseHeader('Content-Type') || 'text/plain'\n const responseBlob = new Blob([this.responseBufferToText()], {\n type: mimeType,\n })\n\n this.logger.info(\n 'resolved response Blob (mime type: %s)',\n responseBlob,\n mimeType\n )\n\n return responseBlob\n }\n\n default: {\n const responseText = this.responseBufferToText()\n this.logger.info(\n 'resolving \"%s\" response type as text',\n this.request.responseType,\n responseText\n )\n\n return responseText\n }\n }\n }\n\n get responseText(): string {\n /**\n * Throw when trying to read the response body as text when the\n * \"responseType\" doesn't expect text. This just respects the spec better.\n * @see https://xhr.spec.whatwg.org/#the-responsetext-attribute\n */\n invariant(\n this.request.responseType === '' || this.request.responseType === 'text',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (\n this.request.readyState !== this.request.LOADING &&\n this.request.readyState !== this.request.DONE\n ) {\n return ''\n }\n\n const responseText = this.responseBufferToText()\n this.logger.info('getResponseText: \"%s\"', responseText)\n\n return responseText\n }\n\n get responseXML(): Document | null {\n invariant(\n this.request.responseType === '' ||\n this.request.responseType === 'document',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n const contentType = this.request.getResponseHeader('Content-Type') || ''\n\n if (typeof DOMParser === 'undefined') {\n console.warn(\n 'Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly.'\n )\n return null\n }\n\n if (isDomParserSupportedType(contentType)) {\n return new DOMParser().parseFromString(\n this.responseBufferToText(),\n contentType\n )\n }\n\n return null\n }\n\n public errorWith(error?: Error): void {\n /**\n * @note Mark this request as handled even if it received a mock error.\n * This prevents the controller from trying to perform this request as-is.\n */\n this[kIsRequestHandled] = true\n this.logger.info('responding with an error')\n\n this.setReadyState(this.request.DONE)\n this.trigger('error', this.request)\n this.trigger('loadend', this.request)\n }\n\n /**\n * Transitions this request's `readyState` to the given one.\n */\n private setReadyState(nextReadyState: number): void {\n this.logger.info(\n 'setReadyState: %d -> %d',\n this.request.readyState,\n nextReadyState\n )\n\n if (this.request.readyState === nextReadyState) {\n this.logger.info('ready state identical, skipping transition...')\n return\n }\n\n define(this.request, 'readyState', nextReadyState)\n\n this.logger.info('set readyState to: %d', nextReadyState)\n\n if (nextReadyState !== this.request.UNSENT) {\n this.logger.info('triggerring \"readystatechange\" event...')\n\n this.trigger('readystatechange', this.request)\n }\n }\n\n /**\n * Triggers given event on the `XMLHttpRequest` instance.\n */\n private trigger<\n EventName extends keyof (XMLHttpRequestEventTargetEventMap & {\n readystatechange: ProgressEvent\n })\n >(\n eventName: EventName,\n target: XMLHttpRequest | XMLHttpRequestUpload,\n options?: ProgressEventInit\n ): void {\n const callback = (target as XMLHttpRequest)[`on${eventName}`]\n const event = createEvent(target, eventName, options)\n\n this.logger.info('trigger \"%s\"', eventName, options || '')\n\n // Invoke direct callbacks.\n if (typeof callback === 'function') {\n this.logger.info('found a direct \"%s\" callback, calling...', eventName)\n callback.call(target as XMLHttpRequest, event)\n }\n\n // Invoke event listeners.\n const events =\n target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events\n\n for (const [registeredEventName, listeners] of events) {\n if (registeredEventName === eventName) {\n this.logger.info(\n 'found %d listener(s) for \"%s\" event, calling...',\n listeners.length,\n eventName\n )\n\n listeners.forEach((listener) => listener.call(target, event))\n }\n }\n }\n\n /**\n * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance.\n */\n private toFetchApiRequest(\n body: XMLHttpRequestBodyInit | Document | null | undefined\n ): Request {\n this.logger.info('converting request to a Fetch API Request...')\n\n // If the `Document` is used as the body of this XMLHttpRequest,\n // set its inner text as the Fetch API Request body.\n const resolvedBody =\n body instanceof Document ? body.documentElement.innerText : body\n\n const fetchRequest = new Request(this.url.href, {\n method: this.method,\n headers: this.requestHeaders,\n /**\n * @see https://xhr.spec.whatwg.org/#cross-origin-credentials\n */\n credentials: this.request.withCredentials ? 'include' : 'same-origin',\n body: ['GET', 'HEAD'].includes(this.method.toUpperCase())\n ? null\n : resolvedBody,\n })\n\n const proxyHeaders = createProxy(fetchRequest.headers, {\n methodCall: ([methodName, args], invoke) => {\n // Forward the latest state of the internal request headers\n // because the interceptor might have modified them\n // without responding to the request.\n switch (methodName) {\n case 'append':\n case 'set': {\n const [headerName, headerValue] = args as [string, string]\n this.request.setRequestHeader(headerName, headerValue)\n break\n }\n\n case 'delete': {\n const [headerName] = args as [string]\n console.warn(\n `XMLHttpRequest: Cannot remove a \"${headerName}\" header from the Fetch API representation of the \"${fetchRequest.method} ${fetchRequest.url}\" request. XMLHttpRequest headers cannot be removed.`\n )\n break\n }\n }\n\n return invoke()\n },\n })\n define(fetchRequest, 'headers', proxyHeaders)\n\n this.logger.info('converted request to a Fetch API Request!', fetchRequest)\n\n return fetchRequest\n }\n}\n\nfunction toAbsoluteUrl(url: string | URL): URL {\n /**\n * @note XMLHttpRequest interceptor may run in environments\n * that implement XMLHttpRequest but don't implement \"location\"\n * (for example, React Native). If that's the case, return the\n * input URL as-is (nothing to be relative to).\n * @see https://github.com/mswjs/msw/issues/1777\n */\n if (typeof location === 'undefined') {\n return new URL(url)\n }\n\n return new URL(url.toString(), location.href)\n}\n\nfunction define(\n target: object,\n property: string | symbol,\n value: unknown\n): void {\n Reflect.defineProperty(target, property, {\n // Ensure writable properties to allow redefining readonly properties.\n writable: true,\n enumerable: true,\n value,\n })\n}\n","/**\n * Concatenate two `Uint8Array` buffers.\n */\nexport function concatArrayBuffer(\n left: Uint8Array,\n right: Uint8Array\n): Uint8Array {\n const result = new Uint8Array(left.byteLength + right.byteLength)\n result.set(left, 0)\n result.set(right, left.byteLength)\n return result\n}\n","export class EventPolyfill implements Event {\n readonly NONE = 0\n readonly CAPTURING_PHASE = 1\n readonly AT_TARGET = 2\n readonly BUBBLING_PHASE = 3\n\n public type: string = ''\n public srcElement: EventTarget | null = null\n public target: EventTarget | null\n public currentTarget: EventTarget | null = null\n public eventPhase: number = 0\n public timeStamp: number\n public isTrusted: boolean = true\n public composed: boolean = false\n public cancelable: boolean = true\n public defaultPrevented: boolean = false\n public bubbles: boolean = true\n public lengthComputable: boolean = true\n public loaded: number = 0\n public total: number = 0\n\n cancelBubble: boolean = false\n returnValue: boolean = true\n\n constructor(\n type: string,\n options?: { target: EventTarget; currentTarget: EventTarget }\n ) {\n this.type = type\n this.target = options?.target || null\n this.currentTarget = options?.currentTarget || null\n this.timeStamp = Date.now()\n }\n\n public composedPath(): EventTarget[] {\n return []\n }\n\n public initEvent(type: string, bubbles?: boolean, cancelable?: boolean) {\n this.type = type\n this.bubbles = !!bubbles\n this.cancelable = !!cancelable\n }\n\n public preventDefault() {\n this.defaultPrevented = true\n }\n\n public stopPropagation() {}\n public stopImmediatePropagation() {}\n}\n","import { EventPolyfill } from './EventPolyfill'\n\nexport class ProgressEventPolyfill extends EventPolyfill {\n readonly lengthComputable: boolean\n readonly composed: boolean\n readonly loaded: number\n readonly total: number\n\n constructor(type: string, init?: ProgressEventInit) {\n super(type)\n\n this.lengthComputable = init?.lengthComputable || false\n this.composed = init?.composed || false\n this.loaded = init?.loaded || 0\n this.total = init?.total || 0\n }\n}\n","import { EventPolyfill } from '../polyfills/EventPolyfill'\nimport { ProgressEventPolyfill } from '../polyfills/ProgressEventPolyfill'\n\nconst SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== 'undefined'\n\nexport function createEvent(\n target: XMLHttpRequest | XMLHttpRequestUpload,\n type: string,\n init?: ProgressEventInit\n): EventPolyfill | ProgressEvent {\n const progressEvents = [\n 'error',\n 'progress',\n 'loadstart',\n 'loadend',\n 'load',\n 'timeout',\n 'abort',\n ]\n\n /**\n * `ProgressEvent` is not supported in React Native.\n * @see https://github.com/mswjs/interceptors/issues/40\n */\n const ProgressEventClass = SUPPORTS_PROGRESS_EVENT\n ? ProgressEvent\n : ProgressEventPolyfill\n\n const event = progressEvents.includes(type)\n ? new ProgressEventClass(type, {\n lengthComputable: true,\n loaded: init?.loaded || 0,\n total: init?.total || 0,\n })\n : new EventPolyfill(type, {\n target,\n currentTarget: target,\n })\n\n return event\n}\n","/**\n * Returns the source object of the given property on the target object\n * (the target itself, any parent in its prototype, or null).\n */\nexport function findPropertySource(\n target: object,\n propertyName: string | symbol\n): object | null {\n if (!(propertyName in target)) {\n return null\n }\n\n const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName)\n if (hasProperty) {\n return target\n }\n\n const prototype = Reflect.getPrototypeOf(target)\n return prototype ? findPropertySource(prototype, propertyName) : null\n}\n","import { findPropertySource } from './findPropertySource'\n\nexport interface ProxyOptions> {\n constructorCall?(args: Array, next: NextFunction): Target\n\n methodCall?(\n this: Target,\n data: [methodName: F, args: Array],\n next: NextFunction\n ): void\n\n setProperty?(\n data: [propertyName: string | symbol, nextValue: unknown],\n next: NextFunction\n ): boolean\n\n getProperty?(\n data: [propertyName: string | symbol, receiver: Target],\n next: NextFunction\n ): void\n}\n\nexport type NextFunction = () => ReturnType\n\nexport function createProxy(\n target: Target,\n options: ProxyOptions\n): Target {\n const proxy = new Proxy(target, optionsToProxyHandler(options))\n\n return proxy\n}\n\nfunction optionsToProxyHandler>(\n options: ProxyOptions\n): ProxyHandler {\n const { constructorCall, methodCall, getProperty, setProperty } = options\n const handler: ProxyHandler = {}\n\n if (typeof constructorCall !== 'undefined') {\n handler.construct = function (target, args, newTarget) {\n const next = Reflect.construct.bind(null, target as any, args, newTarget)\n return constructorCall.call(newTarget, args, next)\n }\n }\n\n handler.set = function (target, propertyName, nextValue) {\n const next = () => {\n const propertySource = findPropertySource(target, propertyName) || target\n const ownDescriptors = Reflect.getOwnPropertyDescriptor(\n propertySource,\n propertyName\n )\n\n // Respect any custom setters present for this property.\n if (typeof ownDescriptors?.set !== 'undefined') {\n ownDescriptors.set.apply(target, [nextValue])\n return true\n }\n\n // Otherwise, set the property on the source.\n return Reflect.defineProperty(propertySource, propertyName, {\n writable: true,\n enumerable: true,\n configurable: true,\n value: nextValue,\n })\n }\n\n if (typeof setProperty !== 'undefined') {\n return setProperty.call(target, [propertyName, nextValue], next)\n }\n\n return next()\n }\n\n handler.get = function (target, propertyName, receiver) {\n /**\n * @note Using `Reflect.get()` here causes \"TypeError: Illegal invocation\".\n */\n const next = () => target[propertyName as any]\n\n const value =\n typeof getProperty !== 'undefined'\n ? getProperty.call(target, [propertyName, receiver], next)\n : next()\n\n if (typeof value === 'function') {\n return (...args: Array) => {\n const next = value.bind(target, ...args)\n\n if (typeof methodCall !== 'undefined') {\n return methodCall.call(target, [propertyName as any, args], next)\n }\n\n return next()\n }\n }\n\n return value\n }\n\n return handler\n}\n","export function isDomParserSupportedType(\n type: string\n): type is DOMParserSupportedType {\n const supportedTypes: Array = [\n 'application/xhtml+xml',\n 'application/xml',\n 'image/svg+xml',\n 'text/html',\n 'text/xml',\n ]\n return supportedTypes.some((supportedType) => {\n return type.startsWith(supportedType)\n })\n}\n","/**\n * Parses a given string into JSON.\n * Gracefully handles invalid JSON by returning `null`.\n */\nexport function parseJson(data: string): Record | null {\n try {\n const json = JSON.parse(data)\n return json\n } catch (_) {\n return null\n }\n}\n","import { FetchResponse } from '../../../utils/fetchUtils'\n\n/**\n * Creates a Fetch API `Response` instance from the given\n * `XMLHttpRequest` instance and a response body.\n */\nexport function createResponse(\n request: XMLHttpRequest,\n body: BodyInit | null\n): Response {\n /**\n * Handle XMLHttpRequest responses that must have null as the\n * response body when represented using Fetch API Response.\n * XMLHttpRequest response will always have an empty string\n * as the \"request.response\" in those cases, resulting in an error\n * when constructing a Response instance.\n * @see https://github.com/mswjs/interceptors/issues/379\n */\n const responseBodyOrNull = FetchResponse.isResponseWithBody(request.status)\n ? body\n : null\n\n return new FetchResponse(responseBodyOrNull, {\n url: request.responseURL,\n status: request.status,\n statusText: request.statusText,\n headers: createHeadersFromXMLHttpReqestHeaders(\n request.getAllResponseHeaders()\n ),\n })\n}\n\nfunction createHeadersFromXMLHttpReqestHeaders(headersString: string): Headers {\n const headers = new Headers()\n\n const lines = headersString.split(/[\\r\\n]+/)\n for (const line of lines) {\n if (line.trim() === '') {\n continue\n }\n\n const [name, ...parts] = line.split(': ')\n const value = parts.join(': ')\n\n headers.append(name, value)\n }\n\n return headers\n}\n","/**\n * Return a total byte length of the given request/response body.\n * If the `Content-Length` header is present, it will be used as the byte length.\n */\nexport async function getBodyByteLength(\n input: Request | Response\n): Promise {\n const explicitContentLength = input.headers.get('content-length')\n\n if (explicitContentLength != null && explicitContentLength !== '') {\n return Number(explicitContentLength)\n }\n\n const buffer = await input.arrayBuffer()\n return buffer.byteLength\n}\n","import type { Logger } from '@open-draft/logger'\nimport { XMLHttpRequestEmitter } from '.'\nimport { RequestController } from '../../RequestController'\nimport { XMLHttpRequestController } from './XMLHttpRequestController'\nimport { handleRequest } from '../../utils/handleRequest'\n\nexport interface XMLHttpRequestProxyOptions {\n emitter: XMLHttpRequestEmitter\n logger: Logger\n}\n\n/**\n * Create a proxied `XMLHttpRequest` class.\n * The proxied class establishes spies on certain methods,\n * allowing us to intercept requests and respond to them.\n */\nexport function createXMLHttpRequestProxy({\n emitter,\n logger,\n}: XMLHttpRequestProxyOptions) {\n const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {\n construct(target, args, newTarget) {\n logger.info('constructed new XMLHttpRequest')\n\n const originalRequest = Reflect.construct(\n target,\n args,\n newTarget\n ) as XMLHttpRequest\n\n /**\n * @note Forward prototype descriptors onto the proxied object.\n * XMLHttpRequest is implemented in JSDOM in a way that assigns\n * a bunch of descriptors, like \"set responseType()\" on the prototype.\n * With this propagation, we make sure that those descriptors trigger\n * when the user operates with the proxied request instance.\n */\n const prototypeDescriptors = Object.getOwnPropertyDescriptors(\n target.prototype\n )\n for (const propertyName in prototypeDescriptors) {\n Reflect.defineProperty(\n originalRequest,\n propertyName,\n prototypeDescriptors[propertyName]\n )\n }\n\n const xhrRequestController = new XMLHttpRequestController(\n originalRequest,\n logger\n )\n\n xhrRequestController.onRequest = async function ({ request, requestId }) {\n const controller = new RequestController(request)\n\n this.logger.info('awaiting mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n controller,\n emitter,\n onResponse: async (response) => {\n await this.respondWith(response)\n },\n onRequestError: () => {\n this.errorWith(new TypeError('Network error'))\n },\n onError: (error) => {\n this.logger.info('request errored!', { error })\n\n if (error instanceof Error) {\n this.errorWith(error)\n }\n },\n })\n\n if (!isRequestHandled) {\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n }\n }\n\n xhrRequestController.onResponse = async function ({\n response,\n isMockedResponse,\n request,\n requestId,\n }) {\n this.logger.info(\n 'emitting the \"response\" event for %s listener(s)...',\n emitter.listenerCount('response')\n )\n\n emitter.emit('response', {\n response,\n isMockedResponse,\n request,\n requestId,\n })\n }\n\n // Return the proxied request from the controller\n // so that the controller can react to the consumer's interactions\n // with this request (opening/sending/etc).\n return xhrRequestController.request\n },\n })\n\n return XMLHttpRequestProxy\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/glossary-6564c252.d.ts b/node_modules/@mswjs/interceptors/lib/browser/glossary-6564c252.d.ts new file mode 100644 index 0000000000..8a08d254a7 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/glossary-6564c252.d.ts @@ -0,0 +1,67 @@ +import { DeferredPromise } from '@open-draft/deferred-promise'; + +declare const kRequestHandled: unique symbol; +declare const kResponsePromise: unique symbol; +declare class RequestController { + private request; + /** + * Internal response promise. + * Available only for the library internals to grab the + * response instance provided by the developer. + * @note This promise cannot be rejected. It's either infinitely + * pending or resolved with whichever Response was passed to `respondWith()`. + */ + [kResponsePromise]: DeferredPromise; + /** + * Internal flag indicating if this request has been handled. + * @note The response promise becomes "fulfilled" on the next tick. + */ + [kRequestHandled]: boolean; + constructor(request: Request); + /** + * Respond to this request with the given `Response` instance. + * @example + * controller.respondWith(new Response()) + * controller.respondWith(Response.json({ id })) + * controller.respondWith(Response.error()) + */ + respondWith(response: Response): void; + /** + * Error this request with the given error. + * @example + * controller.errorWith() + * controller.errorWith(new Error('Oops!')) + */ + errorWith(error?: Error): void; +} + +declare const IS_PATCHED_MODULE: unique symbol; + +type RequestCredentials = 'omit' | 'include' | 'same-origin'; +type HttpRequestEventMap = { + request: [ + args: { + request: Request; + requestId: string; + controller: RequestController; + } + ]; + response: [ + args: { + response: Response; + isMockedResponse: boolean; + request: Request; + requestId: string; + } + ]; + unhandledException: [ + args: { + error: unknown; + request: Request; + requestId: string; + controller: RequestController; + } + ]; +}; + +export { HttpRequestEventMap as H, IS_PATCHED_MODULE as I, RequestController as R, RequestCredentials as a }; diff --git a/node_modules/@mswjs/interceptors/lib/browser/index.d.ts b/node_modules/@mswjs/interceptors/lib/browser/index.d.ts new file mode 100644 index 0000000000..dfd8e4852b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/index.d.ts @@ -0,0 +1,69 @@ +export { H as HttpRequestEventMap, I as IS_PATCHED_MODULE, R as RequestController, a as RequestCredentials } from './glossary-6564c252.js'; +import { I as Interceptor, E as ExtractEventNames } from './Interceptor-af98b768.js'; +export { c as INTERNAL_REQUEST_ID_HEADER_NAME, a as InterceptorEventMap, e as InterceptorReadyState, b as InterceptorSubscription, d as deleteGlobalSymbol, g as getGlobalSymbol } from './Interceptor-af98b768.js'; +import { EventMap, Listener } from 'strict-event-emitter'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; + +interface BatchInterceptorOptions>> { + name: string; + interceptors: InterceptorList; +} +type ExtractEventMapType>> = InterceptorList extends ReadonlyArray ? InterceptorType extends Interceptor ? EventMap : never : never; +/** + * A batch interceptor that exposes a single interface + * to apply and operate with multiple interceptors at once. + */ +declare class BatchInterceptor>, Events extends EventMap = ExtractEventMapType> extends Interceptor { + static symbol: symbol; + private interceptors; + constructor(options: BatchInterceptorOptions); + protected setup(): void; + on>(event: EventName, listener: Listener): this; + once>(event: EventName, listener: Listener): this; + off>(event: EventName, listener: Listener): this; + removeAllListeners>(event?: EventName | undefined): this; +} + +/** + * Generate a random ID string to represent a request. + * @example + * createRequestId() + * // "f774b6c9c600f" + */ +declare function createRequestId(): string; + +/** + * Removes query parameters and hashes from a given URL. + */ +declare function getCleanUrl(url: URL, isAbsolute?: boolean): string; + +declare function encodeBuffer(text: string): Uint8Array; +declare function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string; + +interface FetchResponseInit extends ResponseInit { + url?: string; +} +declare class FetchResponse extends Response { + /** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ + static readonly STATUS_CODES_WITHOUT_BODY: number[]; + static readonly STATUS_CODES_WITH_REDIRECT: number[]; + static isConfigurableStatusCode(status: number): boolean; + static isRedirectResponse(status: number): boolean; + /** + * Returns a boolean indicating whether the given response status + * code represents a response that can have a body. + */ + static isResponseWithBody(status: number): boolean; + static setUrl(url: string | undefined, response: Response): void; + /** + * Parses the given raw HTTP headers into a Fetch API `Headers` instance. + */ + static parseRawHeaders(rawHeaders: Array): Headers; + constructor(body?: BodyInit | null, init?: FetchResponseInit); +} + +export { BatchInterceptor, BatchInterceptorOptions, ExtractEventMapType, ExtractEventNames, FetchResponse, Interceptor, createRequestId, decodeBuffer, encodeBuffer, getCleanUrl }; diff --git a/node_modules/@mswjs/interceptors/lib/browser/index.js b/node_modules/@mswjs/interceptors/lib/browser/index.js new file mode 100644 index 0000000000..a8aaa1208a --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/index.js @@ -0,0 +1,79 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + + +var _chunkLK6DILFKjs = require('./chunk-LK6DILFK.js'); + + + +var _chunkBC2BLJQNjs = require('./chunk-BC2BLJQN.js'); + + + + + + + +var _chunkTIPR373Rjs = require('./chunk-TIPR373R.js'); + +// src/BatchInterceptor.ts +var BatchInterceptor = class extends _chunkTIPR373Rjs.Interceptor { + constructor(options) { + BatchInterceptor.symbol = Symbol(options.name); + super(BatchInterceptor.symbol); + this.interceptors = options.interceptors; + } + setup() { + const logger = this.logger.extend("setup"); + logger.info("applying all %d interceptors...", this.interceptors.length); + for (const interceptor of this.interceptors) { + logger.info('applying "%s" interceptor...', interceptor.constructor.name); + interceptor.apply(); + logger.info("adding interceptor dispose subscription"); + this.subscriptions.push(() => interceptor.dispose()); + } + } + on(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.on(event, listener); + } + return this; + } + once(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.once(event, listener); + } + return this; + } + off(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.off(event, listener); + } + return this; + } + removeAllListeners(event) { + for (const interceptors of this.interceptors) { + interceptors.removeAllListeners(event); + } + return this; + } +}; + +// src/utils/getCleanUrl.ts +function getCleanUrl(url, isAbsolute = true) { + return [isAbsolute && url.origin, url.pathname].filter(Boolean).join(""); +} + + + + + + + + + + + + + +exports.BatchInterceptor = BatchInterceptor; exports.FetchResponse = _chunkBC2BLJQNjs.FetchResponse; exports.INTERNAL_REQUEST_ID_HEADER_NAME = _chunkTIPR373Rjs.INTERNAL_REQUEST_ID_HEADER_NAME; exports.IS_PATCHED_MODULE = _chunkBC2BLJQNjs.IS_PATCHED_MODULE; exports.Interceptor = _chunkTIPR373Rjs.Interceptor; exports.InterceptorReadyState = _chunkTIPR373Rjs.InterceptorReadyState; exports.createRequestId = _chunkTIPR373Rjs.createRequestId; exports.decodeBuffer = _chunkLK6DILFKjs.decodeBuffer; exports.deleteGlobalSymbol = _chunkTIPR373Rjs.deleteGlobalSymbol; exports.encodeBuffer = _chunkLK6DILFKjs.encodeBuffer; exports.getCleanUrl = getCleanUrl; exports.getGlobalSymbol = _chunkTIPR373Rjs.getGlobalSymbol; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/index.js.map b/node_modules/@mswjs/interceptors/lib/browser/index.js.map new file mode 100644 index 0000000000..34e4b31b1d --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/BatchInterceptor.ts","../../src/utils/getCleanUrl.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;;;AC3FO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE","sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray>\n> = InterceptorList extends ReadonlyArray\n ? InterceptorType extends Interceptor\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray>,\n Events extends EventMap = ExtractEventMapType\n> extends Interceptor {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n","/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/index.mjs b/node_modules/@mswjs/interceptors/lib/browser/index.mjs new file mode 100644 index 0000000000..77c7a04bc9 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/index.mjs @@ -0,0 +1,79 @@ +import { + decodeBuffer, + encodeBuffer +} from "./chunk-6HYIRFX2.mjs"; +import { + FetchResponse, + IS_PATCHED_MODULE +} from "./chunk-5UK33FSU.mjs"; +import { + INTERNAL_REQUEST_ID_HEADER_NAME, + Interceptor, + InterceptorReadyState, + createRequestId, + deleteGlobalSymbol, + getGlobalSymbol +} from "./chunk-QED3Q6Z2.mjs"; + +// src/BatchInterceptor.ts +var BatchInterceptor = class extends Interceptor { + constructor(options) { + BatchInterceptor.symbol = Symbol(options.name); + super(BatchInterceptor.symbol); + this.interceptors = options.interceptors; + } + setup() { + const logger = this.logger.extend("setup"); + logger.info("applying all %d interceptors...", this.interceptors.length); + for (const interceptor of this.interceptors) { + logger.info('applying "%s" interceptor...', interceptor.constructor.name); + interceptor.apply(); + logger.info("adding interceptor dispose subscription"); + this.subscriptions.push(() => interceptor.dispose()); + } + } + on(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.on(event, listener); + } + return this; + } + once(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.once(event, listener); + } + return this; + } + off(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.off(event, listener); + } + return this; + } + removeAllListeners(event) { + for (const interceptors of this.interceptors) { + interceptors.removeAllListeners(event); + } + return this; + } +}; + +// src/utils/getCleanUrl.ts +function getCleanUrl(url, isAbsolute = true) { + return [isAbsolute && url.origin, url.pathname].filter(Boolean).join(""); +} +export { + BatchInterceptor, + FetchResponse, + INTERNAL_REQUEST_ID_HEADER_NAME, + IS_PATCHED_MODULE, + Interceptor, + InterceptorReadyState, + createRequestId, + decodeBuffer, + deleteGlobalSymbol, + encodeBuffer, + getCleanUrl, + getGlobalSymbol +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/index.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/index.mjs.map new file mode 100644 index 0000000000..4cc8acce11 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/BatchInterceptor.ts","../../src/utils/getCleanUrl.ts"],"sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray>\n> = InterceptorList extends ReadonlyArray\n ? InterceptorType extends Interceptor\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray>,\n Events extends EventMap = ExtractEventMapType\n> extends Interceptor {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n","/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;;;AC3FO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.d.ts b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.d.ts new file mode 100644 index 0000000000..d6ab505119 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.d.ts @@ -0,0 +1,233 @@ +import { I as Interceptor } from '../../Interceptor-af98b768.js'; +import '@open-draft/logger'; +import 'strict-event-emitter'; + +interface CloseEventInit extends EventInit { + code?: number; + reason?: string; + wasClean?: boolean; +} +declare class CloseEvent extends Event { + code: number; + reason: string; + wasClean: boolean; + constructor(type: string, init?: CloseEventInit); +} + +type WebSocketData = string | ArrayBufferLike | Blob | ArrayBufferView; +type WebSocketTransportEventMap = { + incoming: MessageEvent; + outgoing: MessageEvent; + close: CloseEvent; +}; +type StrictEventListenerOrEventListenerObject = ((this: WebSocket, event: EventType) => void) | { + handleEvent(this: WebSocket, event: EventType): void; +}; +interface WebSocketTransport { + addEventListener(event: EventType, listener: StrictEventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; + dispatchEvent(event: WebSocketTransportEventMap[EventType]): boolean; + /** + * Send the data from the server to this client. + */ + send(data: WebSocketData): void; + /** + * Close the client connection. + */ + close(code?: number, reason?: string): void; +} + +type WebSocketEventListener = (this: WebSocket, event: EventType) => void; +declare const kPassthroughPromise: unique symbol; +declare const kOnSend: unique symbol; +declare const kClose: unique symbol; +declare class WebSocketOverride extends EventTarget implements WebSocket { + static readonly CONNECTING = 0; + static readonly OPEN = 1; + static readonly CLOSING = 2; + static readonly CLOSED = 3; + readonly CONNECTING = 0; + readonly OPEN = 1; + readonly CLOSING = 2; + readonly CLOSED = 3; + url: string; + protocol: string; + extensions: string; + binaryType: BinaryType; + readyState: number; + bufferedAmount: number; + private _onopen; + private _onmessage; + private _onerror; + private _onclose; + private [kPassthroughPromise]; + private [kOnSend]?; + constructor(url: string | URL, protocols?: string | Array); + set onopen(listener: WebSocketEventListener | null); + get onopen(): WebSocketEventListener | null; + set onmessage(listener: WebSocketEventListener> | null); + get onmessage(): WebSocketEventListener> | null; + set onerror(listener: WebSocketEventListener | null); + get onerror(): WebSocketEventListener | null; + set onclose(listener: WebSocketEventListener | null); + get onclose(): WebSocketEventListener | null; + /** + * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0 + */ + send(data: WebSocketData): void; + close(code?: number, reason?: string): void; + private [kClose]; + addEventListener(type: K, listener: (this: WebSocket, event: WebSocketEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, callback: EventListenerOrEventListenerObject | null, options?: boolean | EventListenerOptions): void; +} + +declare const kEmitter$1: unique symbol; +interface WebSocketClientEventMap { + message: MessageEvent; + close: CloseEvent; +} +interface WebSocketClientConnectionProtocol { + id: string; + url: URL; + send(data: WebSocketData): void; + close(code?: number, reason?: string): void; +} +/** + * The WebSocket client instance represents an incoming + * client connection. The user can control the connection, + * send and receive events. + */ +declare class WebSocketClientConnection implements WebSocketClientConnectionProtocol { + readonly socket: WebSocket; + private readonly transport; + readonly id: string; + readonly url: URL; + private [kEmitter$1]; + constructor(socket: WebSocket, transport: WebSocketTransport); + /** + * Listen for the outgoing events from the connected WebSocket client. + */ + addEventListener(type: EventType, listener: WebSocketEventListener, options?: AddEventListenerOptions | boolean): void; + /** + * Removes the listener for the given event. + */ + removeEventListener(event: EventType, listener: WebSocketEventListener, options?: EventListenerOptions | boolean): void; + /** + * Send data to the connected client. + */ + send(data: WebSocketData): void; + /** + * Close the WebSocket connection. + * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1). + * @param {string} reason A custom connection close reason. + */ + close(code?: number, reason?: string): void; +} + +/** + * Abstraction over the given mock `WebSocket` instance that allows + * for controlling that instance (e.g. sending and receiving messages). + */ +declare class WebSocketClassTransport extends EventTarget implements WebSocketTransport { + protected readonly socket: WebSocketOverride; + constructor(socket: WebSocketOverride); + addEventListener(type: EventType, callback: StrictEventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; + dispatchEvent(event: WebSocketTransportEventMap[EventType]): boolean; + send(data: WebSocketData): void; + close(code: number, reason?: string): void; +} + +declare const kEmitter: unique symbol; +declare const kSend: unique symbol; +interface WebSocketServerEventMap { + open: Event; + message: MessageEvent; + error: Event; + close: CloseEvent; +} +/** + * The WebSocket server instance represents the actual production + * WebSocket server connection. It's idle by default but you can + * establish it by calling `server.connect()`. + */ +declare class WebSocketServerConnection { + private readonly client; + private readonly transport; + private readonly createConnection; + /** + * A WebSocket instance connected to the original server. + */ + private realWebSocket?; + private mockCloseController; + private realCloseController; + private [kEmitter]; + constructor(client: WebSocketOverride, transport: WebSocketClassTransport, createConnection: () => WebSocket); + /** + * The `WebSocket` instance connected to the original server. + * Accessing this before calling `server.connect()` will throw. + */ + get socket(): WebSocket; + /** + * Open connection to the original WebSocket server. + */ + connect(): void; + /** + * Listen for the incoming events from the original WebSocket server. + */ + addEventListener(event: EventType, listener: WebSocketEventListener, options?: AddEventListenerOptions | boolean): void; + /** + * Remove the listener for the given event. + */ + removeEventListener(event: EventType, listener: WebSocketEventListener, options?: EventListenerOptions | boolean): void; + /** + * Send data to the original WebSocket server. + * @example + * server.send('hello') + * server.send(new Blob(['hello'])) + * server.send(new TextEncoder().encode('hello')) + */ + send(data: WebSocketData): void; + private [kSend]; + /** + * Close the actual server connection. + */ + close(): void; + private handleIncomingMessage; + private handleMockClose; + private handleRealClose; +} + +type WebSocketEventMap$1 = { + connection: [args: WebSocketConnectionData]; +}; +type WebSocketConnectionData = { + /** + * The incoming WebSocket client connection. + */ + client: WebSocketClientConnection; + /** + * The original WebSocket server connection. + */ + server: WebSocketServerConnection; + /** + * The connection information. + */ + info: { + /** + * The protocols supported by the WebSocket client. + */ + protocols: string | Array | undefined; + }; +}; +/** + * Intercept the outgoing WebSocket connections created using + * the global `WebSocket` class. + */ +declare class WebSocketInterceptor extends Interceptor { + static symbol: symbol; + constructor(); + protected checkEnvironment(): boolean; + protected setup(): void; +} + +export { WebSocketClientConnection, WebSocketClientConnectionProtocol, WebSocketConnectionData, WebSocketData, WebSocketEventMap$1 as WebSocketEventMap, WebSocketInterceptor, WebSocketServerConnection, WebSocketTransport }; diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.js b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.js new file mode 100644 index 0000000000..b0462ac126 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.js @@ -0,0 +1,710 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkPFGO5BSMjs = require('../../chunk-PFGO5BSM.js'); + + + +var _chunkTIPR373Rjs = require('../../chunk-TIPR373R.js'); + +// src/interceptors/WebSocket/utils/bindEvent.ts +function bindEvent(target, event) { + Object.defineProperties(event, { + target: { + value: target, + enumerable: true, + writable: true + }, + currentTarget: { + value: target, + enumerable: true, + writable: true + } + }); + return event; +} + +// src/interceptors/WebSocket/utils/events.ts +var kCancelable = Symbol("kCancelable"); +var kDefaultPrevented = Symbol("kDefaultPrevented"); +var CancelableMessageEvent = class extends MessageEvent { + constructor(type, init) { + super(type, init); + this[kCancelable] = !!init.cancelable; + this[kDefaultPrevented] = false; + } + get cancelable() { + return this[kCancelable]; + } + set cancelable(nextCancelable) { + this[kCancelable] = nextCancelable; + } + get defaultPrevented() { + return this[kDefaultPrevented]; + } + set defaultPrevented(nextDefaultPrevented) { + this[kDefaultPrevented] = nextDefaultPrevented; + } + preventDefault() { + if (this.cancelable && !this[kDefaultPrevented]) { + this[kDefaultPrevented] = true; + } + } +}; +kCancelable, kDefaultPrevented; +var CloseEvent = class extends Event { + constructor(type, init = {}) { + super(type, init); + this.code = init.code === void 0 ? 0 : init.code; + this.reason = init.reason === void 0 ? "" : init.reason; + this.wasClean = init.wasClean === void 0 ? false : init.wasClean; + } +}; +var CancelableCloseEvent = class extends CloseEvent { + constructor(type, init = {}) { + super(type, init); + this[kCancelable] = !!init.cancelable; + this[kDefaultPrevented] = false; + } + get cancelable() { + return this[kCancelable]; + } + set cancelable(nextCancelable) { + this[kCancelable] = nextCancelable; + } + get defaultPrevented() { + return this[kDefaultPrevented]; + } + set defaultPrevented(nextDefaultPrevented) { + this[kDefaultPrevented] = nextDefaultPrevented; + } + preventDefault() { + if (this.cancelable && !this[kDefaultPrevented]) { + this[kDefaultPrevented] = true; + } + } +}; +kCancelable, kDefaultPrevented; + +// src/interceptors/WebSocket/WebSocketClientConnection.ts +var kEmitter = Symbol("kEmitter"); +var kBoundListener = Symbol("kBoundListener"); +var WebSocketClientConnection = class { + constructor(socket, transport) { + this.socket = socket; + this.transport = transport; + this.id = _chunkTIPR373Rjs.createRequestId.call(void 0, ); + this.url = new URL(socket.url); + this[kEmitter] = new EventTarget(); + this.transport.addEventListener("outgoing", (event) => { + const message = bindEvent( + this.socket, + new CancelableMessageEvent("message", { + data: event.data, + origin: event.origin, + cancelable: true + }) + ); + this[kEmitter].dispatchEvent(message); + if (message.defaultPrevented) { + event.preventDefault(); + } + }); + this.transport.addEventListener("close", (event) => { + this[kEmitter].dispatchEvent( + bindEvent(this.socket, new CloseEvent("close", event)) + ); + }); + } + /** + * Listen for the outgoing events from the connected WebSocket client. + */ + addEventListener(type, listener, options) { + if (!Reflect.has(listener, kBoundListener)) { + const boundListener = listener.bind(this.socket); + Object.defineProperty(listener, kBoundListener, { + value: boundListener, + enumerable: false, + configurable: false + }); + } + this[kEmitter].addEventListener( + type, + Reflect.get(listener, kBoundListener), + options + ); + } + /** + * Removes the listener for the given event. + */ + removeEventListener(event, listener, options) { + this[kEmitter].removeEventListener( + event, + Reflect.get(listener, kBoundListener), + options + ); + } + /** + * Send data to the connected client. + */ + send(data) { + this.transport.send(data); + } + /** + * Close the WebSocket connection. + * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1). + * @param {string} reason A custom connection close reason. + */ + close(code, reason) { + this.transport.close(code, reason); + } +}; +kEmitter; + +// src/interceptors/WebSocket/WebSocketServerConnection.ts +var _outvariant = require('outvariant'); + +// src/interceptors/WebSocket/WebSocketOverride.ts + +var _deferredpromise = require('@open-draft/deferred-promise'); +var WEBSOCKET_CLOSE_CODE_RANGE_ERROR = "InvalidAccessError: close code out of user configurable range"; +var kPassthroughPromise = Symbol("kPassthroughPromise"); +var kOnSend = Symbol("kOnSend"); +var kClose = Symbol("kClose"); +var WebSocketOverride = class extends EventTarget { + constructor(url, protocols) { + super(); + this.CONNECTING = 0; + this.OPEN = 1; + this.CLOSING = 2; + this.CLOSED = 3; + this._onopen = null; + this._onmessage = null; + this._onerror = null; + this._onclose = null; + this.url = url.toString(); + this.protocol = ""; + this.extensions = ""; + this.binaryType = "blob"; + this.readyState = this.CONNECTING; + this.bufferedAmount = 0; + this[kPassthroughPromise] = new (0, _deferredpromise.DeferredPromise)(); + queueMicrotask(async () => { + if (await this[kPassthroughPromise]) { + return; + } + this.protocol = typeof protocols === "string" ? protocols : Array.isArray(protocols) && protocols.length > 0 ? protocols[0] : ""; + if (this.readyState === this.CONNECTING) { + this.readyState = this.OPEN; + this.dispatchEvent(bindEvent(this, new Event("open"))); + } + }); + } + set onopen(listener) { + this.removeEventListener("open", this._onopen); + this._onopen = listener; + if (listener !== null) { + this.addEventListener("open", listener); + } + } + get onopen() { + return this._onopen; + } + set onmessage(listener) { + this.removeEventListener( + "message", + this._onmessage + ); + this._onmessage = listener; + if (listener !== null) { + this.addEventListener("message", listener); + } + } + get onmessage() { + return this._onmessage; + } + set onerror(listener) { + this.removeEventListener("error", this._onerror); + this._onerror = listener; + if (listener !== null) { + this.addEventListener("error", listener); + } + } + get onerror() { + return this._onerror; + } + set onclose(listener) { + this.removeEventListener("close", this._onclose); + this._onclose = listener; + if (listener !== null) { + this.addEventListener("close", listener); + } + } + get onclose() { + return this._onclose; + } + /** + * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0 + */ + send(data) { + if (this.readyState === this.CONNECTING) { + this.close(); + throw new DOMException("InvalidStateError"); + } + if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) { + return; + } + this.bufferedAmount += getDataSize(data); + queueMicrotask(() => { + var _a; + this.bufferedAmount = 0; + (_a = this[kOnSend]) == null ? void 0 : _a.call(this, data); + }); + } + close(code = 1e3, reason) { + _outvariant.invariant.call(void 0, code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR); + _outvariant.invariant.call(void 0, + code === 1e3 || code >= 3e3 && code <= 4999, + WEBSOCKET_CLOSE_CODE_RANGE_ERROR + ); + this[kClose](code, reason); + } + [(kPassthroughPromise, kOnSend, kClose)](code = 1e3, reason, wasClean = true) { + if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) { + return; + } + this.readyState = this.CLOSING; + queueMicrotask(() => { + this.readyState = this.CLOSED; + this.dispatchEvent( + bindEvent( + this, + new CloseEvent("close", { + code, + reason, + wasClean + }) + ) + ); + this._onopen = null; + this._onmessage = null; + this._onerror = null; + this._onclose = null; + }); + } + addEventListener(type, listener, options) { + return super.addEventListener( + type, + listener, + options + ); + } + removeEventListener(type, callback, options) { + return super.removeEventListener(type, callback, options); + } +}; +WebSocketOverride.CONNECTING = 0; +WebSocketOverride.OPEN = 1; +WebSocketOverride.CLOSING = 2; +WebSocketOverride.CLOSED = 3; +function getDataSize(data) { + if (typeof data === "string") { + return data.length; + } + if (data instanceof Blob) { + return data.size; + } + return data.byteLength; +} + +// src/interceptors/WebSocket/WebSocketServerConnection.ts +var kEmitter2 = Symbol("kEmitter"); +var kBoundListener2 = Symbol("kBoundListener"); +var kSend = Symbol("kSend"); +var WebSocketServerConnection = class { + constructor(client, transport, createConnection) { + this.client = client; + this.transport = transport; + this.createConnection = createConnection; + this[kEmitter2] = new EventTarget(); + this.mockCloseController = new AbortController(); + this.realCloseController = new AbortController(); + this.transport.addEventListener("outgoing", (event) => { + if (typeof this.realWebSocket === "undefined") { + return; + } + queueMicrotask(() => { + if (!event.defaultPrevented) { + this[kSend](event.data); + } + }); + }); + this.transport.addEventListener( + "incoming", + this.handleIncomingMessage.bind(this) + ); + } + /** + * The `WebSocket` instance connected to the original server. + * Accessing this before calling `server.connect()` will throw. + */ + get socket() { + _outvariant.invariant.call(void 0, + this.realWebSocket, + 'Cannot access "socket" on the original WebSocket server object: the connection is not open. Did you forget to call `server.connect()`?' + ); + return this.realWebSocket; + } + /** + * Open connection to the original WebSocket server. + */ + connect() { + _outvariant.invariant.call(void 0, + !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN, + 'Failed to call "connect()" on the original WebSocket instance: the connection already open' + ); + const realWebSocket = this.createConnection(); + realWebSocket.binaryType = this.client.binaryType; + realWebSocket.addEventListener( + "open", + (event) => { + this[kEmitter2].dispatchEvent( + bindEvent(this.realWebSocket, new Event("open", event)) + ); + }, + { once: true } + ); + realWebSocket.addEventListener("message", (event) => { + this.transport.dispatchEvent( + bindEvent( + this.realWebSocket, + new MessageEvent("incoming", { + data: event.data, + origin: event.origin + }) + ) + ); + }); + this.client.addEventListener( + "close", + (event) => { + this.handleMockClose(event); + }, + { + signal: this.mockCloseController.signal + } + ); + realWebSocket.addEventListener( + "close", + (event) => { + this.handleRealClose(event); + }, + { + signal: this.realCloseController.signal + } + ); + realWebSocket.addEventListener("error", () => { + const errorEvent = bindEvent( + realWebSocket, + new Event("error", { cancelable: true }) + ); + this[kEmitter2].dispatchEvent(errorEvent); + if (!errorEvent.defaultPrevented) { + this.client.dispatchEvent(bindEvent(this.client, new Event("error"))); + } + }); + this.realWebSocket = realWebSocket; + } + /** + * Listen for the incoming events from the original WebSocket server. + */ + addEventListener(event, listener, options) { + if (!Reflect.has(listener, kBoundListener2)) { + const boundListener = listener.bind(this.client); + Object.defineProperty(listener, kBoundListener2, { + value: boundListener, + enumerable: false + }); + } + this[kEmitter2].addEventListener( + event, + Reflect.get(listener, kBoundListener2), + options + ); + } + /** + * Remove the listener for the given event. + */ + removeEventListener(event, listener, options) { + this[kEmitter2].removeEventListener( + event, + Reflect.get(listener, kBoundListener2), + options + ); + } + /** + * Send data to the original WebSocket server. + * @example + * server.send('hello') + * server.send(new Blob(['hello'])) + * server.send(new TextEncoder().encode('hello')) + */ + send(data) { + this[kSend](data); + } + [(kEmitter2, kSend)](data) { + const { realWebSocket } = this; + _outvariant.invariant.call(void 0, + realWebSocket, + 'Failed to call "server.send()" for "%s": the connection is not open. Did you forget to call "server.connect()"?', + this.client.url + ); + if (realWebSocket.readyState === WebSocket.CLOSING || realWebSocket.readyState === WebSocket.CLOSED) { + return; + } + if (realWebSocket.readyState === WebSocket.CONNECTING) { + realWebSocket.addEventListener( + "open", + () => { + realWebSocket.send(data); + }, + { once: true } + ); + return; + } + realWebSocket.send(data); + } + /** + * Close the actual server connection. + */ + close() { + const { realWebSocket } = this; + _outvariant.invariant.call(void 0, + realWebSocket, + 'Failed to close server connection for "%s": the connection is not open. Did you forget to call "server.connect()"?', + this.client.url + ); + this.realCloseController.abort(); + if (realWebSocket.readyState === WebSocket.CLOSING || realWebSocket.readyState === WebSocket.CLOSED) { + return; + } + realWebSocket.close(); + queueMicrotask(() => { + this[kEmitter2].dispatchEvent( + bindEvent( + this.realWebSocket, + new CancelableCloseEvent("close", { + /** + * @note `server.close()` in the interceptor + * always results in clean closures. + */ + code: 1e3, + cancelable: true + }) + ) + ); + }); + } + handleIncomingMessage(event) { + const messageEvent = bindEvent( + event.target, + new CancelableMessageEvent("message", { + data: event.data, + origin: event.origin, + cancelable: true + }) + ); + this[kEmitter2].dispatchEvent(messageEvent); + if (!messageEvent.defaultPrevented) { + this.client.dispatchEvent( + bindEvent( + /** + * @note Bind the forwarded original server events + * to the mock WebSocket instance so it would + * dispatch them straight away. + */ + this.client, + // Clone the message event again to prevent + // the "already being dispatched" exception. + new MessageEvent("message", { + data: event.data, + origin: event.origin + }) + ) + ); + } + } + handleMockClose(_event) { + if (this.realWebSocket) { + this.realWebSocket.close(); + } + } + handleRealClose(event) { + this.mockCloseController.abort(); + const closeEvent = bindEvent( + this.realWebSocket, + new CancelableCloseEvent("close", { + code: event.code, + reason: event.reason, + wasClean: event.wasClean, + cancelable: true + }) + ); + this[kEmitter2].dispatchEvent(closeEvent); + if (!closeEvent.defaultPrevented) { + this.client[kClose](event.code, event.reason); + } + } +}; + +// src/interceptors/WebSocket/WebSocketClassTransport.ts +var WebSocketClassTransport = class extends EventTarget { + constructor(socket) { + super(); + this.socket = socket; + this.socket.addEventListener("close", (event) => { + this.dispatchEvent(bindEvent(this.socket, new CloseEvent("close", event))); + }); + this.socket[kOnSend] = (data) => { + this.dispatchEvent( + bindEvent( + this.socket, + // Dispatch this as cancelable because "client" connection + // re-creates this message event (cannot dispatch the same event). + new CancelableMessageEvent("outgoing", { + data, + origin: this.socket.url, + cancelable: true + }) + ) + ); + }; + } + addEventListener(type, callback, options) { + return super.addEventListener(type, callback, options); + } + dispatchEvent(event) { + return super.dispatchEvent(event); + } + send(data) { + queueMicrotask(() => { + if (this.socket.readyState === this.socket.CLOSING || this.socket.readyState === this.socket.CLOSED) { + return; + } + const dispatchEvent = () => { + this.socket.dispatchEvent( + bindEvent( + /** + * @note Setting this event's "target" to the + * WebSocket override instance is important. + * This way it can tell apart original incoming events + * (must be forwarded to the transport) from the + * mocked message events like the one below + * (must be dispatched on the client instance). + */ + this.socket, + new MessageEvent("message", { + data, + origin: this.socket.url + }) + ) + ); + }; + if (this.socket.readyState === this.socket.CONNECTING) { + this.socket.addEventListener( + "open", + () => { + dispatchEvent(); + }, + { once: true } + ); + } else { + dispatchEvent(); + } + }); + } + close(code, reason) { + this.socket[kClose](code, reason); + } +}; + +// src/interceptors/WebSocket/index.ts +var _WebSocketInterceptor = class extends _chunkTIPR373Rjs.Interceptor { + constructor() { + super(_WebSocketInterceptor.symbol); + } + checkEnvironment() { + return _chunkPFGO5BSMjs.hasConfigurableGlobal.call(void 0, "WebSocket"); + } + setup() { + const originalWebSocketDescriptor = Object.getOwnPropertyDescriptor( + globalThis, + "WebSocket" + ); + const WebSocketProxy = new Proxy(globalThis.WebSocket, { + construct: (target, args, newTarget) => { + const [url, protocols] = args; + const createConnection = () => { + return Reflect.construct(target, args, newTarget); + }; + const socket = new WebSocketOverride(url, protocols); + const transport = new WebSocketClassTransport(socket); + queueMicrotask(() => { + try { + const server = new WebSocketServerConnection( + socket, + transport, + createConnection + ); + const hasConnectionListeners = this.emitter.emit("connection", { + client: new WebSocketClientConnection(socket, transport), + server, + info: { + protocols + } + }); + if (hasConnectionListeners) { + socket[kPassthroughPromise].resolve(false); + } else { + socket[kPassthroughPromise].resolve(true); + server.connect(); + server.addEventListener("open", () => { + socket.dispatchEvent(bindEvent(socket, new Event("open"))); + if (server["realWebSocket"]) { + socket.protocol = server["realWebSocket"].protocol; + } + }); + } + } catch (error) { + if (error instanceof Error) { + socket.dispatchEvent(new Event("error")); + if (socket.readyState !== WebSocket.CLOSING && socket.readyState !== WebSocket.CLOSED) { + socket[kClose](1011, error.message, false); + } + console.error(error); + } + } + }); + return socket; + } + }); + Object.defineProperty(globalThis, "WebSocket", { + value: WebSocketProxy, + configurable: true + }); + this.subscriptions.push(() => { + Object.defineProperty( + globalThis, + "WebSocket", + originalWebSocketDescriptor + ); + }); + } +}; +var WebSocketInterceptor = _WebSocketInterceptor; +WebSocketInterceptor.symbol = Symbol("websocket"); + + + + +exports.WebSocketClientConnection = WebSocketClientConnection; exports.WebSocketInterceptor = WebSocketInterceptor; exports.WebSocketServerConnection = WebSocketServerConnection; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.js.map b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.js.map new file mode 100644 index 0000000000..755f2f1b09 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../../../src/interceptors/WebSocket/utils/bindEvent.ts","../../../../src/interceptors/WebSocket/utils/events.ts","../../../../src/interceptors/WebSocket/WebSocketClientConnection.ts","../../../../src/interceptors/WebSocket/WebSocketServerConnection.ts","../../../../src/interceptors/WebSocket/WebSocketOverride.ts","../../../../src/interceptors/WebSocket/WebSocketClassTransport.ts","../../../../src/interceptors/WebSocket/index.ts"],"names":["invariant","kEmitter","kBoundListener"],"mappings":"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","sourcesContent":["type EventWithTarget = E & { target: T }\n\nexport function bindEvent(\n target: T,\n event: E\n): EventWithTarget {\n Object.defineProperties(event, {\n target: {\n value: target,\n enumerable: true,\n writable: true,\n },\n currentTarget: {\n value: target,\n enumerable: true,\n writable: true,\n },\n })\n\n return event as EventWithTarget\n}\n","const kCancelable = Symbol('kCancelable')\nconst kDefaultPrevented = Symbol('kDefaultPrevented')\n\n/**\n * A `MessageEvent` superset that supports event cancellation\n * in Node.js. It's rather non-intrusive so it can be safely\n * used in the browser as well.\n *\n * @see https://github.com/nodejs/node/issues/51767\n */\nexport class CancelableMessageEvent extends MessageEvent {\n [kCancelable]: boolean;\n [kDefaultPrevented]: boolean\n\n constructor(type: string, init: MessageEventInit) {\n super(type, init)\n this[kCancelable] = !!init.cancelable\n this[kDefaultPrevented] = false\n }\n\n get cancelable() {\n return this[kCancelable]\n }\n\n set cancelable(nextCancelable) {\n this[kCancelable] = nextCancelable\n }\n\n get defaultPrevented() {\n return this[kDefaultPrevented]\n }\n\n set defaultPrevented(nextDefaultPrevented) {\n this[kDefaultPrevented] = nextDefaultPrevented\n }\n\n public preventDefault(): void {\n if (this.cancelable && !this[kDefaultPrevented]) {\n this[kDefaultPrevented] = true\n }\n }\n}\n\ninterface CloseEventInit extends EventInit {\n code?: number\n reason?: string\n wasClean?: boolean\n}\n\nexport class CloseEvent extends Event {\n public code: number\n public reason: string\n public wasClean: boolean\n\n constructor(type: string, init: CloseEventInit = {}) {\n super(type, init)\n this.code = init.code === undefined ? 0 : init.code\n this.reason = init.reason === undefined ? '' : init.reason\n this.wasClean = init.wasClean === undefined ? false : init.wasClean\n }\n}\n\nexport class CancelableCloseEvent extends CloseEvent {\n [kCancelable]: boolean;\n [kDefaultPrevented]: boolean\n\n constructor(type: string, init: CloseEventInit = {}) {\n super(type, init)\n this[kCancelable] = !!init.cancelable\n this[kDefaultPrevented] = false\n }\n\n get cancelable() {\n return this[kCancelable]\n }\n\n set cancelable(nextCancelable) {\n this[kCancelable] = nextCancelable\n }\n\n get defaultPrevented() {\n return this[kDefaultPrevented]\n }\n\n set defaultPrevented(nextDefaultPrevented) {\n this[kDefaultPrevented] = nextDefaultPrevented\n }\n\n public preventDefault(): void {\n if (this.cancelable && !this[kDefaultPrevented]) {\n this[kDefaultPrevented] = true\n }\n }\n}\n","import type { WebSocketData, WebSocketTransport } from './WebSocketTransport'\nimport type { WebSocketEventListener } from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\nimport { createRequestId } from '../../createRequestId'\n\nconst kEmitter = Symbol('kEmitter')\nconst kBoundListener = Symbol('kBoundListener')\n\ninterface WebSocketClientEventMap {\n message: MessageEvent\n close: CloseEvent\n}\n\nexport interface WebSocketClientConnectionProtocol {\n id: string\n url: URL\n send(data: WebSocketData): void\n close(code?: number, reason?: string): void\n}\n\n/**\n * The WebSocket client instance represents an incoming\n * client connection. The user can control the connection,\n * send and receive events.\n */\nexport class WebSocketClientConnection\n implements WebSocketClientConnectionProtocol\n{\n public readonly id: string\n public readonly url: URL\n\n private [kEmitter]: EventTarget\n\n constructor(\n public readonly socket: WebSocket,\n private readonly transport: WebSocketTransport\n ) {\n this.id = createRequestId()\n this.url = new URL(socket.url)\n this[kEmitter] = new EventTarget()\n\n // Emit outgoing client data (\"ws.send()\") as \"message\"\n // events on the \"client\" connection.\n this.transport.addEventListener('outgoing', (event) => {\n const message = bindEvent(\n this.socket,\n new CancelableMessageEvent('message', {\n data: event.data,\n origin: event.origin,\n cancelable: true,\n })\n )\n\n this[kEmitter].dispatchEvent(message)\n\n // This is a bit silly but forward the cancellation state\n // of the \"client\" message event to the \"outgoing\" transport event.\n // This way, other agens (like \"server\" connection) can know\n // whether the client listener has pervented the default.\n if (message.defaultPrevented) {\n event.preventDefault()\n }\n })\n\n /**\n * Emit the \"close\" event on the \"client\" connection\n * whenever the underlying transport is closed.\n * @note \"client.close()\" does NOT dispatch the \"close\"\n * event on the WebSocket because it uses non-configurable\n * close status code. Thus, we listen to the transport\n * instead of the WebSocket's \"close\" event.\n */\n this.transport.addEventListener('close', (event) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.socket, new CloseEvent('close', event))\n )\n })\n }\n\n /**\n * Listen for the outgoing events from the connected WebSocket client.\n */\n public addEventListener(\n type: EventType,\n listener: WebSocketEventListener,\n options?: AddEventListenerOptions | boolean\n ): void {\n if (!Reflect.has(listener, kBoundListener)) {\n const boundListener = listener.bind(this.socket)\n\n // Store the bound listener on the original listener\n // so the exact bound function can be accessed in \"removeEventListener()\".\n Object.defineProperty(listener, kBoundListener, {\n value: boundListener,\n enumerable: false,\n configurable: false,\n })\n }\n\n this[kEmitter].addEventListener(\n type,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Removes the listener for the given event.\n */\n public removeEventListener(\n event: EventType,\n listener: WebSocketEventListener,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Send data to the connected client.\n */\n public send(data: WebSocketData): void {\n this.transport.send(data)\n }\n\n /**\n * Close the WebSocket connection.\n * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1).\n * @param {string} reason A custom connection close reason.\n */\n public close(code?: number, reason?: string): void {\n this.transport.close(code, reason)\n }\n}\n","import { invariant } from 'outvariant'\nimport {\n kClose,\n WebSocketEventListener,\n WebSocketOverride,\n} from './WebSocketOverride'\nimport type { WebSocketData } from './WebSocketTransport'\nimport type { WebSocketClassTransport } from './WebSocketClassTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport {\n CancelableMessageEvent,\n CancelableCloseEvent,\n CloseEvent,\n} from './utils/events'\n\nconst kEmitter = Symbol('kEmitter')\nconst kBoundListener = Symbol('kBoundListener')\nconst kSend = Symbol('kSend')\n\ninterface WebSocketServerEventMap {\n open: Event\n message: MessageEvent\n error: Event\n close: CloseEvent\n}\n\n/**\n * The WebSocket server instance represents the actual production\n * WebSocket server connection. It's idle by default but you can\n * establish it by calling `server.connect()`.\n */\nexport class WebSocketServerConnection {\n /**\n * A WebSocket instance connected to the original server.\n */\n private realWebSocket?: WebSocket\n private mockCloseController: AbortController\n private realCloseController: AbortController\n private [kEmitter]: EventTarget\n\n constructor(\n private readonly client: WebSocketOverride,\n private readonly transport: WebSocketClassTransport,\n private readonly createConnection: () => WebSocket\n ) {\n this[kEmitter] = new EventTarget()\n this.mockCloseController = new AbortController()\n this.realCloseController = new AbortController()\n\n // Automatically forward outgoing client events\n // to the actual server unless the outgoing message event\n // has been prevented. The \"outgoing\" transport event it\n // dispatched by the \"client\" connection.\n this.transport.addEventListener('outgoing', (event) => {\n // Ignore client messages if the server connection\n // hasn't been established yet. Nowhere to forward.\n if (typeof this.realWebSocket === 'undefined') {\n return\n }\n\n // Every outgoing client message can prevent this forwarding\n // by preventing the default of the outgoing message event.\n // This listener will be added before user-defined listeners,\n // so execute the logic on the next tick.\n queueMicrotask(() => {\n if (!event.defaultPrevented) {\n /**\n * @note Use the internal send mechanism so consumers can tell\n * apart direct user calls to `server.send()` and internal calls.\n * E.g. MSW has to ignore this internal call to log out messages correctly.\n */\n this[kSend](event.data)\n }\n })\n })\n\n this.transport.addEventListener(\n 'incoming',\n this.handleIncomingMessage.bind(this)\n )\n }\n\n /**\n * The `WebSocket` instance connected to the original server.\n * Accessing this before calling `server.connect()` will throw.\n */\n public get socket(): WebSocket {\n invariant(\n this.realWebSocket,\n 'Cannot access \"socket\" on the original WebSocket server object: the connection is not open. Did you forget to call `server.connect()`?'\n )\n\n return this.realWebSocket\n }\n\n /**\n * Open connection to the original WebSocket server.\n */\n public connect(): void {\n invariant(\n !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN,\n 'Failed to call \"connect()\" on the original WebSocket instance: the connection already open'\n )\n\n const realWebSocket = this.createConnection()\n\n // Inherit the binary type from the mock WebSocket client.\n realWebSocket.binaryType = this.client.binaryType\n\n // Allow the interceptor to listen to when the server connection\n // has been established. This isn't necessary to operate with the connection\n // but may be beneficial in some cases (like conditionally adding logging).\n realWebSocket.addEventListener(\n 'open',\n (event) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.realWebSocket!, new Event('open', event))\n )\n },\n { once: true }\n )\n\n realWebSocket.addEventListener('message', (event) => {\n // Dispatch the \"incoming\" transport event instead of\n // invoking the internal handler directly. This way,\n // anyone can listen to the \"incoming\" event but this\n // class is the one resulting in it.\n this.transport.dispatchEvent(\n bindEvent(\n this.realWebSocket!,\n new MessageEvent('incoming', {\n data: event.data,\n origin: event.origin,\n })\n )\n )\n })\n\n // Close the original connection when the mock client closes.\n // E.g. \"client.close()\" was called. This is never forwarded anywhere.\n this.client.addEventListener(\n 'close',\n (event) => {\n this.handleMockClose(event)\n },\n {\n signal: this.mockCloseController.signal,\n }\n )\n\n // Forward the \"close\" event to let the interceptor handle\n // closures initiated by the original server.\n realWebSocket.addEventListener(\n 'close',\n (event) => {\n this.handleRealClose(event)\n },\n {\n signal: this.realCloseController.signal,\n }\n )\n\n realWebSocket.addEventListener('error', () => {\n const errorEvent = bindEvent(\n realWebSocket,\n new Event('error', { cancelable: true })\n )\n\n // Emit the \"error\" event on the `server` connection\n // to let the interceptor react to original server errors.\n this[kEmitter].dispatchEvent(errorEvent)\n\n // If the error event from the original server hasn't been prevented,\n // forward it to the underlying client.\n if (!errorEvent.defaultPrevented) {\n this.client.dispatchEvent(bindEvent(this.client, new Event('error')))\n }\n })\n\n this.realWebSocket = realWebSocket\n }\n\n /**\n * Listen for the incoming events from the original WebSocket server.\n */\n public addEventListener(\n event: EventType,\n listener: WebSocketEventListener,\n options?: AddEventListenerOptions | boolean\n ): void {\n if (!Reflect.has(listener, kBoundListener)) {\n const boundListener = listener.bind(this.client)\n\n // Store the bound listener on the original listener\n // so the exact bound function can be accessed in \"removeEventListener()\".\n Object.defineProperty(listener, kBoundListener, {\n value: boundListener,\n enumerable: false,\n })\n }\n\n this[kEmitter].addEventListener(\n event,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Remove the listener for the given event.\n */\n public removeEventListener(\n event: EventType,\n listener: WebSocketEventListener,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Send data to the original WebSocket server.\n * @example\n * server.send('hello')\n * server.send(new Blob(['hello']))\n * server.send(new TextEncoder().encode('hello'))\n */\n public send(data: WebSocketData): void {\n this[kSend](data)\n }\n\n private [kSend](data: WebSocketData): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to call \"server.send()\" for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.client.url\n )\n\n // Silently ignore writes on the closed original WebSocket.\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n // Delegate the send to when the original connection is open.\n // Unlike the mock, connecting to the original server may take time\n // so we cannot call this on the next tick.\n if (realWebSocket.readyState === WebSocket.CONNECTING) {\n realWebSocket.addEventListener(\n 'open',\n () => {\n realWebSocket.send(data)\n },\n { once: true }\n )\n return\n }\n\n // Send the data to the original WebSocket server.\n realWebSocket.send(data)\n }\n\n /**\n * Close the actual server connection.\n */\n public close(): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to close server connection for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.client.url\n )\n\n // Remove the \"close\" event listener from the server\n // so it doesn't close the underlying WebSocket client\n // when you call \"server.close()\". This also prevents the\n // `close` event on the `server` connection from being dispatched twice.\n this.realCloseController.abort()\n\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n // Close the actual client connection.\n realWebSocket.close()\n\n // Dispatch the \"close\" event on the `server` connection.\n queueMicrotask(() => {\n this[kEmitter].dispatchEvent(\n bindEvent(\n this.realWebSocket,\n new CancelableCloseEvent('close', {\n /**\n * @note `server.close()` in the interceptor\n * always results in clean closures.\n */\n code: 1000,\n cancelable: true,\n })\n )\n )\n })\n }\n\n private handleIncomingMessage(event: MessageEvent): void {\n // Clone the event to dispatch it on this class\n // once again and prevent the \"already being dispatched\"\n // exception. Clone it here so we can observe this event\n // being prevented in the \"server.on()\" listeners.\n const messageEvent = bindEvent(\n event.target,\n new CancelableMessageEvent('message', {\n data: event.data,\n origin: event.origin,\n cancelable: true,\n })\n )\n\n /**\n * @note Emit \"message\" event on the server connection\n * instance to let the interceptor know about these\n * incoming events from the original server. In that listener,\n * the interceptor can modify or skip the event forwarding\n * to the mock WebSocket instance.\n */\n this[kEmitter].dispatchEvent(messageEvent)\n\n /**\n * @note Forward the incoming server events to the client.\n * Preventing the default on the message event stops this.\n */\n if (!messageEvent.defaultPrevented) {\n this.client.dispatchEvent(\n bindEvent(\n /**\n * @note Bind the forwarded original server events\n * to the mock WebSocket instance so it would\n * dispatch them straight away.\n */\n this.client,\n // Clone the message event again to prevent\n // the \"already being dispatched\" exception.\n new MessageEvent('message', {\n data: event.data,\n origin: event.origin,\n })\n )\n )\n }\n }\n\n private handleMockClose(_event: Event): void {\n // Close the original connection if the mock client closes.\n if (this.realWebSocket) {\n this.realWebSocket.close()\n }\n }\n\n private handleRealClose(event: CloseEvent): void {\n // For closures originating from the original server,\n // remove the \"close\" listener from the mock client.\n // original close -> (?) client[kClose]() --X--> \"close\" (again).\n this.mockCloseController.abort()\n\n const closeEvent = bindEvent(\n this.realWebSocket,\n new CancelableCloseEvent('close', {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean,\n cancelable: true,\n })\n )\n\n this[kEmitter].dispatchEvent(closeEvent)\n\n // If the close event from the server hasn't been prevented,\n // forward the closure to the mock client.\n if (!closeEvent.defaultPrevented) {\n // Close the intercepted client forcefully to\n // allow non-configurable status codes from the server.\n // If the socket has been closed by now, no harm calling\n // this again—it will have no effect.\n this.client[kClose](event.code, event.reason)\n }\n }\n}\n","import { invariant } from 'outvariant'\nimport type { WebSocketData } from './WebSocketTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport { CloseEvent } from './utils/events'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\n\nexport type WebSocketEventListener<\n EventType extends WebSocketEventMap[keyof WebSocketEventMap] = Event\n> = (this: WebSocket, event: EventType) => void\n\nconst WEBSOCKET_CLOSE_CODE_RANGE_ERROR =\n 'InvalidAccessError: close code out of user configurable range'\n\nexport const kPassthroughPromise = Symbol('kPassthroughPromise')\nexport const kOnSend = Symbol('kOnSend')\nexport const kClose = Symbol('kClose')\n\nexport class WebSocketOverride extends EventTarget implements WebSocket {\n static readonly CONNECTING = 0\n static readonly OPEN = 1\n static readonly CLOSING = 2\n static readonly CLOSED = 3\n readonly CONNECTING = 0\n readonly OPEN = 1\n readonly CLOSING = 2\n readonly CLOSED = 3\n\n public url: string\n public protocol: string\n public extensions: string\n public binaryType: BinaryType\n public readyState: number\n public bufferedAmount: number\n\n private _onopen: WebSocketEventListener | null = null\n private _onmessage: WebSocketEventListener<\n MessageEvent\n > | null = null\n private _onerror: WebSocketEventListener | null = null\n private _onclose: WebSocketEventListener | null = null\n\n private [kPassthroughPromise]: DeferredPromise\n private [kOnSend]?: (data: WebSocketData) => void\n\n constructor(url: string | URL, protocols?: string | Array) {\n super()\n this.url = url.toString()\n this.protocol = ''\n this.extensions = ''\n this.binaryType = 'blob'\n this.readyState = this.CONNECTING\n this.bufferedAmount = 0\n\n this[kPassthroughPromise] = new DeferredPromise()\n\n queueMicrotask(async () => {\n if (await this[kPassthroughPromise]) {\n return\n }\n\n this.protocol =\n typeof protocols === 'string'\n ? protocols\n : Array.isArray(protocols) && protocols.length > 0\n ? protocols[0]\n : ''\n\n /**\n * @note Check that nothing has prevented this connection\n * (e.g. called `client.close()` in the connection listener).\n * If the connection has been prevented, never dispatch the open event,.\n */\n if (this.readyState === this.CONNECTING) {\n this.readyState = this.OPEN\n this.dispatchEvent(bindEvent(this, new Event('open')))\n }\n })\n }\n\n set onopen(listener: WebSocketEventListener | null) {\n this.removeEventListener('open', this._onopen)\n this._onopen = listener\n if (listener !== null) {\n this.addEventListener('open', listener)\n }\n }\n get onopen(): WebSocketEventListener | null {\n return this._onopen\n }\n\n set onmessage(\n listener: WebSocketEventListener> | null\n ) {\n this.removeEventListener(\n 'message',\n this._onmessage as WebSocketEventListener\n )\n this._onmessage = listener\n if (listener !== null) {\n this.addEventListener('message', listener)\n }\n }\n get onmessage(): WebSocketEventListener> | null {\n return this._onmessage\n }\n\n set onerror(listener: WebSocketEventListener | null) {\n this.removeEventListener('error', this._onerror)\n this._onerror = listener\n if (listener !== null) {\n this.addEventListener('error', listener)\n }\n }\n get onerror(): WebSocketEventListener | null {\n return this._onerror\n }\n\n set onclose(listener: WebSocketEventListener | null) {\n this.removeEventListener('close', this._onclose as WebSocketEventListener)\n this._onclose = listener\n if (listener !== null) {\n this.addEventListener('close', listener)\n }\n }\n get onclose(): WebSocketEventListener | null {\n return this._onclose\n }\n\n /**\n * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0\n */\n public send(data: WebSocketData): void {\n if (this.readyState === this.CONNECTING) {\n this.close()\n throw new DOMException('InvalidStateError')\n }\n\n // Sending when the socket is about to close\n // discards the sent data.\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n // Buffer the data to send in this even loop\n // but send it in the next.\n this.bufferedAmount += getDataSize(data)\n\n queueMicrotask(() => {\n // This is a bit optimistic but since no actual data transfer\n // is involved, all the data will be \"sent\" on the next tick.\n this.bufferedAmount = 0\n\n /**\n * @note Notify the parent about outgoing data.\n * This notifies the transport and the connection\n * listens to the outgoing data to emit the \"message\" event.\n */\n this[kOnSend]?.(data)\n })\n }\n\n public close(code: number = 1000, reason?: string): void {\n invariant(code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR)\n invariant(\n code === 1000 || (code >= 3000 && code <= 4999),\n WEBSOCKET_CLOSE_CODE_RANGE_ERROR\n )\n\n this[kClose](code, reason)\n }\n\n private [kClose](\n code: number = 1000,\n reason?: string,\n wasClean = true\n ): void {\n /**\n * @note Move this check here so that even internall closures,\n * like those triggered by the `server` connection, are not\n * performed twice.\n */\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n this.readyState = this.CLOSING\n\n queueMicrotask(() => {\n this.readyState = this.CLOSED\n\n this.dispatchEvent(\n bindEvent(\n this,\n new CloseEvent('close', {\n code,\n reason,\n wasClean,\n })\n )\n )\n\n // Remove all event listeners once the socket is closed.\n this._onopen = null\n this._onmessage = null\n this._onerror = null\n this._onclose = null\n })\n }\n\n public addEventListener(\n type: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: unknown,\n listener: unknown,\n options?: unknown\n ): void {\n return super.addEventListener(\n type as string,\n listener as EventListener,\n options as AddEventListenerOptions\n )\n }\n\n removeEventListener(\n type: K,\n callback: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void {\n return super.removeEventListener(type, callback, options)\n }\n}\n\nfunction getDataSize(data: WebSocketData): number {\n if (typeof data === 'string') {\n return data.length\n }\n\n if (data instanceof Blob) {\n return data.size\n }\n\n return data.byteLength\n}\n","import { bindEvent } from './utils/bindEvent'\nimport {\n StrictEventListenerOrEventListenerObject,\n WebSocketData,\n WebSocketTransport,\n WebSocketTransportEventMap,\n} from './WebSocketTransport'\nimport { kOnSend, kClose, WebSocketOverride } from './WebSocketOverride'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\n\n/**\n * Abstraction over the given mock `WebSocket` instance that allows\n * for controlling that instance (e.g. sending and receiving messages).\n */\nexport class WebSocketClassTransport\n extends EventTarget\n implements WebSocketTransport\n{\n constructor(protected readonly socket: WebSocketOverride) {\n super()\n\n // Emit the \"close\" event on the transport if the close\n // originates from the WebSocket client. E.g. the application\n // calls \"ws.close()\", not the interceptor.\n this.socket.addEventListener('close', (event) => {\n this.dispatchEvent(bindEvent(this.socket, new CloseEvent('close', event)))\n })\n\n /**\n * Emit the \"outgoing\" event on the transport\n * whenever the WebSocket client sends data (\"ws.send()\").\n */\n this.socket[kOnSend] = (data) => {\n this.dispatchEvent(\n bindEvent(\n this.socket,\n // Dispatch this as cancelable because \"client\" connection\n // re-creates this message event (cannot dispatch the same event).\n new CancelableMessageEvent('outgoing', {\n data,\n origin: this.socket.url,\n cancelable: true,\n })\n )\n )\n }\n }\n\n public addEventListener(\n type: EventType,\n callback: StrictEventListenerOrEventListenerObject<\n WebSocketTransportEventMap[EventType]\n > | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n return super.addEventListener(type, callback as EventListener, options)\n }\n\n public dispatchEvent(\n event: WebSocketTransportEventMap[EventType]\n ): boolean {\n return super.dispatchEvent(event)\n }\n\n public send(data: WebSocketData): void {\n queueMicrotask(() => {\n if (\n this.socket.readyState === this.socket.CLOSING ||\n this.socket.readyState === this.socket.CLOSED\n ) {\n return\n }\n\n const dispatchEvent = () => {\n this.socket.dispatchEvent(\n bindEvent(\n /**\n * @note Setting this event's \"target\" to the\n * WebSocket override instance is important.\n * This way it can tell apart original incoming events\n * (must be forwarded to the transport) from the\n * mocked message events like the one below\n * (must be dispatched on the client instance).\n */\n this.socket,\n new MessageEvent('message', {\n data,\n origin: this.socket.url,\n })\n )\n )\n }\n\n if (this.socket.readyState === this.socket.CONNECTING) {\n this.socket.addEventListener(\n 'open',\n () => {\n dispatchEvent()\n },\n { once: true }\n )\n } else {\n dispatchEvent()\n }\n })\n }\n\n public close(code: number, reason?: string): void {\n /**\n * @note Call the internal close method directly\n * to allow closing the connection with the status codes\n * that are non-configurable by the user (> 1000 <= 1015).\n */\n this.socket[kClose](code, reason)\n }\n}\n","import { Interceptor } from '../../Interceptor'\nimport {\n type WebSocketClientConnectionProtocol,\n WebSocketClientConnection,\n} from './WebSocketClientConnection'\nimport { WebSocketServerConnection } from './WebSocketServerConnection'\nimport { WebSocketClassTransport } from './WebSocketClassTransport'\nimport {\n kClose,\n kPassthroughPromise,\n WebSocketOverride,\n} from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\n\nexport { type WebSocketData, WebSocketTransport } from './WebSocketTransport'\nexport {\n WebSocketClientConnection,\n WebSocketClientConnectionProtocol,\n WebSocketServerConnection,\n}\n\nexport type WebSocketEventMap = {\n connection: [args: WebSocketConnectionData]\n}\n\nexport type WebSocketConnectionData = {\n /**\n * The incoming WebSocket client connection.\n */\n client: WebSocketClientConnection\n\n /**\n * The original WebSocket server connection.\n */\n server: WebSocketServerConnection\n\n /**\n * The connection information.\n */\n info: {\n /**\n * The protocols supported by the WebSocket client.\n */\n protocols: string | Array | undefined\n }\n}\n\n/**\n * Intercept the outgoing WebSocket connections created using\n * the global `WebSocket` class.\n */\nexport class WebSocketInterceptor extends Interceptor {\n static symbol = Symbol('websocket')\n\n constructor() {\n super(WebSocketInterceptor.symbol)\n }\n\n protected checkEnvironment(): boolean {\n return hasConfigurableGlobal('WebSocket')\n }\n\n protected setup(): void {\n const originalWebSocketDescriptor = Object.getOwnPropertyDescriptor(\n globalThis,\n 'WebSocket'\n )\n\n const WebSocketProxy = new Proxy(globalThis.WebSocket, {\n construct: (\n target,\n args: ConstructorParameters,\n newTarget\n ) => {\n const [url, protocols] = args\n\n const createConnection = (): WebSocket => {\n return Reflect.construct(target, args, newTarget)\n }\n\n // All WebSocket instances are mocked and don't forward\n // any events to the original server (no connection established).\n // To forward the events, the user must use the \"server.send()\" API.\n const socket = new WebSocketOverride(url, protocols)\n const transport = new WebSocketClassTransport(socket)\n\n // Emit the \"connection\" event to the interceptor on the next tick\n // so the client can modify WebSocket options, like \"binaryType\"\n // while the connection is already pending.\n queueMicrotask(() => {\n try {\n const server = new WebSocketServerConnection(\n socket,\n transport,\n createConnection\n )\n\n // The \"globalThis.WebSocket\" class stands for\n // the client-side connection. Assume it's established\n // as soon as the WebSocket instance is constructed.\n const hasConnectionListeners = this.emitter.emit('connection', {\n client: new WebSocketClientConnection(socket, transport),\n server,\n info: {\n protocols,\n },\n })\n\n if (hasConnectionListeners) {\n socket[kPassthroughPromise].resolve(false)\n } else {\n socket[kPassthroughPromise].resolve(true)\n\n server.connect()\n\n // Forward the \"open\" event from the original server\n // to the mock WebSocket client in the case of a passthrough connection.\n server.addEventListener('open', () => {\n socket.dispatchEvent(bindEvent(socket, new Event('open')))\n\n // Forward the original connection protocol to the\n // mock WebSocket client.\n if (server['realWebSocket']) {\n socket.protocol = server['realWebSocket'].protocol\n }\n })\n }\n } catch (error) {\n /**\n * @note Translate unhandled exceptions during the connection\n * handling (i.e. interceptor exceptions) as WebSocket connection\n * closures with error. This prevents from the exceptions occurring\n * in `queueMicrotask` from being process-wide and uncatchable.\n */\n if (error instanceof Error) {\n socket.dispatchEvent(new Event('error'))\n\n // No need to close the connection if it's already being closed.\n // E.g. the interceptor called `client.close()` and then threw an error.\n if (\n socket.readyState !== WebSocket.CLOSING &&\n socket.readyState !== WebSocket.CLOSED\n ) {\n socket[kClose](1011, error.message, false)\n }\n\n console.error(error)\n }\n }\n })\n\n return socket\n },\n })\n\n Object.defineProperty(globalThis, 'WebSocket', {\n value: WebSocketProxy,\n configurable: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(\n globalThis,\n 'WebSocket',\n originalWebSocketDescriptor!\n )\n })\n }\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.mjs b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.mjs new file mode 100644 index 0000000000..23e52ec202 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.mjs @@ -0,0 +1,710 @@ +import { + hasConfigurableGlobal +} from "../../chunk-TX5GBTFY.mjs"; +import { + Interceptor, + createRequestId +} from "../../chunk-QED3Q6Z2.mjs"; + +// src/interceptors/WebSocket/utils/bindEvent.ts +function bindEvent(target, event) { + Object.defineProperties(event, { + target: { + value: target, + enumerable: true, + writable: true + }, + currentTarget: { + value: target, + enumerable: true, + writable: true + } + }); + return event; +} + +// src/interceptors/WebSocket/utils/events.ts +var kCancelable = Symbol("kCancelable"); +var kDefaultPrevented = Symbol("kDefaultPrevented"); +var CancelableMessageEvent = class extends MessageEvent { + constructor(type, init) { + super(type, init); + this[kCancelable] = !!init.cancelable; + this[kDefaultPrevented] = false; + } + get cancelable() { + return this[kCancelable]; + } + set cancelable(nextCancelable) { + this[kCancelable] = nextCancelable; + } + get defaultPrevented() { + return this[kDefaultPrevented]; + } + set defaultPrevented(nextDefaultPrevented) { + this[kDefaultPrevented] = nextDefaultPrevented; + } + preventDefault() { + if (this.cancelable && !this[kDefaultPrevented]) { + this[kDefaultPrevented] = true; + } + } +}; +kCancelable, kDefaultPrevented; +var CloseEvent = class extends Event { + constructor(type, init = {}) { + super(type, init); + this.code = init.code === void 0 ? 0 : init.code; + this.reason = init.reason === void 0 ? "" : init.reason; + this.wasClean = init.wasClean === void 0 ? false : init.wasClean; + } +}; +var CancelableCloseEvent = class extends CloseEvent { + constructor(type, init = {}) { + super(type, init); + this[kCancelable] = !!init.cancelable; + this[kDefaultPrevented] = false; + } + get cancelable() { + return this[kCancelable]; + } + set cancelable(nextCancelable) { + this[kCancelable] = nextCancelable; + } + get defaultPrevented() { + return this[kDefaultPrevented]; + } + set defaultPrevented(nextDefaultPrevented) { + this[kDefaultPrevented] = nextDefaultPrevented; + } + preventDefault() { + if (this.cancelable && !this[kDefaultPrevented]) { + this[kDefaultPrevented] = true; + } + } +}; +kCancelable, kDefaultPrevented; + +// src/interceptors/WebSocket/WebSocketClientConnection.ts +var kEmitter = Symbol("kEmitter"); +var kBoundListener = Symbol("kBoundListener"); +var WebSocketClientConnection = class { + constructor(socket, transport) { + this.socket = socket; + this.transport = transport; + this.id = createRequestId(); + this.url = new URL(socket.url); + this[kEmitter] = new EventTarget(); + this.transport.addEventListener("outgoing", (event) => { + const message = bindEvent( + this.socket, + new CancelableMessageEvent("message", { + data: event.data, + origin: event.origin, + cancelable: true + }) + ); + this[kEmitter].dispatchEvent(message); + if (message.defaultPrevented) { + event.preventDefault(); + } + }); + this.transport.addEventListener("close", (event) => { + this[kEmitter].dispatchEvent( + bindEvent(this.socket, new CloseEvent("close", event)) + ); + }); + } + /** + * Listen for the outgoing events from the connected WebSocket client. + */ + addEventListener(type, listener, options) { + if (!Reflect.has(listener, kBoundListener)) { + const boundListener = listener.bind(this.socket); + Object.defineProperty(listener, kBoundListener, { + value: boundListener, + enumerable: false, + configurable: false + }); + } + this[kEmitter].addEventListener( + type, + Reflect.get(listener, kBoundListener), + options + ); + } + /** + * Removes the listener for the given event. + */ + removeEventListener(event, listener, options) { + this[kEmitter].removeEventListener( + event, + Reflect.get(listener, kBoundListener), + options + ); + } + /** + * Send data to the connected client. + */ + send(data) { + this.transport.send(data); + } + /** + * Close the WebSocket connection. + * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1). + * @param {string} reason A custom connection close reason. + */ + close(code, reason) { + this.transport.close(code, reason); + } +}; +kEmitter; + +// src/interceptors/WebSocket/WebSocketServerConnection.ts +import { invariant as invariant2 } from "outvariant"; + +// src/interceptors/WebSocket/WebSocketOverride.ts +import { invariant } from "outvariant"; +import { DeferredPromise } from "@open-draft/deferred-promise"; +var WEBSOCKET_CLOSE_CODE_RANGE_ERROR = "InvalidAccessError: close code out of user configurable range"; +var kPassthroughPromise = Symbol("kPassthroughPromise"); +var kOnSend = Symbol("kOnSend"); +var kClose = Symbol("kClose"); +var WebSocketOverride = class extends EventTarget { + constructor(url, protocols) { + super(); + this.CONNECTING = 0; + this.OPEN = 1; + this.CLOSING = 2; + this.CLOSED = 3; + this._onopen = null; + this._onmessage = null; + this._onerror = null; + this._onclose = null; + this.url = url.toString(); + this.protocol = ""; + this.extensions = ""; + this.binaryType = "blob"; + this.readyState = this.CONNECTING; + this.bufferedAmount = 0; + this[kPassthroughPromise] = new DeferredPromise(); + queueMicrotask(async () => { + if (await this[kPassthroughPromise]) { + return; + } + this.protocol = typeof protocols === "string" ? protocols : Array.isArray(protocols) && protocols.length > 0 ? protocols[0] : ""; + if (this.readyState === this.CONNECTING) { + this.readyState = this.OPEN; + this.dispatchEvent(bindEvent(this, new Event("open"))); + } + }); + } + set onopen(listener) { + this.removeEventListener("open", this._onopen); + this._onopen = listener; + if (listener !== null) { + this.addEventListener("open", listener); + } + } + get onopen() { + return this._onopen; + } + set onmessage(listener) { + this.removeEventListener( + "message", + this._onmessage + ); + this._onmessage = listener; + if (listener !== null) { + this.addEventListener("message", listener); + } + } + get onmessage() { + return this._onmessage; + } + set onerror(listener) { + this.removeEventListener("error", this._onerror); + this._onerror = listener; + if (listener !== null) { + this.addEventListener("error", listener); + } + } + get onerror() { + return this._onerror; + } + set onclose(listener) { + this.removeEventListener("close", this._onclose); + this._onclose = listener; + if (listener !== null) { + this.addEventListener("close", listener); + } + } + get onclose() { + return this._onclose; + } + /** + * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0 + */ + send(data) { + if (this.readyState === this.CONNECTING) { + this.close(); + throw new DOMException("InvalidStateError"); + } + if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) { + return; + } + this.bufferedAmount += getDataSize(data); + queueMicrotask(() => { + var _a; + this.bufferedAmount = 0; + (_a = this[kOnSend]) == null ? void 0 : _a.call(this, data); + }); + } + close(code = 1e3, reason) { + invariant(code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR); + invariant( + code === 1e3 || code >= 3e3 && code <= 4999, + WEBSOCKET_CLOSE_CODE_RANGE_ERROR + ); + this[kClose](code, reason); + } + [(kPassthroughPromise, kOnSend, kClose)](code = 1e3, reason, wasClean = true) { + if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) { + return; + } + this.readyState = this.CLOSING; + queueMicrotask(() => { + this.readyState = this.CLOSED; + this.dispatchEvent( + bindEvent( + this, + new CloseEvent("close", { + code, + reason, + wasClean + }) + ) + ); + this._onopen = null; + this._onmessage = null; + this._onerror = null; + this._onclose = null; + }); + } + addEventListener(type, listener, options) { + return super.addEventListener( + type, + listener, + options + ); + } + removeEventListener(type, callback, options) { + return super.removeEventListener(type, callback, options); + } +}; +WebSocketOverride.CONNECTING = 0; +WebSocketOverride.OPEN = 1; +WebSocketOverride.CLOSING = 2; +WebSocketOverride.CLOSED = 3; +function getDataSize(data) { + if (typeof data === "string") { + return data.length; + } + if (data instanceof Blob) { + return data.size; + } + return data.byteLength; +} + +// src/interceptors/WebSocket/WebSocketServerConnection.ts +var kEmitter2 = Symbol("kEmitter"); +var kBoundListener2 = Symbol("kBoundListener"); +var kSend = Symbol("kSend"); +var WebSocketServerConnection = class { + constructor(client, transport, createConnection) { + this.client = client; + this.transport = transport; + this.createConnection = createConnection; + this[kEmitter2] = new EventTarget(); + this.mockCloseController = new AbortController(); + this.realCloseController = new AbortController(); + this.transport.addEventListener("outgoing", (event) => { + if (typeof this.realWebSocket === "undefined") { + return; + } + queueMicrotask(() => { + if (!event.defaultPrevented) { + this[kSend](event.data); + } + }); + }); + this.transport.addEventListener( + "incoming", + this.handleIncomingMessage.bind(this) + ); + } + /** + * The `WebSocket` instance connected to the original server. + * Accessing this before calling `server.connect()` will throw. + */ + get socket() { + invariant2( + this.realWebSocket, + 'Cannot access "socket" on the original WebSocket server object: the connection is not open. Did you forget to call `server.connect()`?' + ); + return this.realWebSocket; + } + /** + * Open connection to the original WebSocket server. + */ + connect() { + invariant2( + !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN, + 'Failed to call "connect()" on the original WebSocket instance: the connection already open' + ); + const realWebSocket = this.createConnection(); + realWebSocket.binaryType = this.client.binaryType; + realWebSocket.addEventListener( + "open", + (event) => { + this[kEmitter2].dispatchEvent( + bindEvent(this.realWebSocket, new Event("open", event)) + ); + }, + { once: true } + ); + realWebSocket.addEventListener("message", (event) => { + this.transport.dispatchEvent( + bindEvent( + this.realWebSocket, + new MessageEvent("incoming", { + data: event.data, + origin: event.origin + }) + ) + ); + }); + this.client.addEventListener( + "close", + (event) => { + this.handleMockClose(event); + }, + { + signal: this.mockCloseController.signal + } + ); + realWebSocket.addEventListener( + "close", + (event) => { + this.handleRealClose(event); + }, + { + signal: this.realCloseController.signal + } + ); + realWebSocket.addEventListener("error", () => { + const errorEvent = bindEvent( + realWebSocket, + new Event("error", { cancelable: true }) + ); + this[kEmitter2].dispatchEvent(errorEvent); + if (!errorEvent.defaultPrevented) { + this.client.dispatchEvent(bindEvent(this.client, new Event("error"))); + } + }); + this.realWebSocket = realWebSocket; + } + /** + * Listen for the incoming events from the original WebSocket server. + */ + addEventListener(event, listener, options) { + if (!Reflect.has(listener, kBoundListener2)) { + const boundListener = listener.bind(this.client); + Object.defineProperty(listener, kBoundListener2, { + value: boundListener, + enumerable: false + }); + } + this[kEmitter2].addEventListener( + event, + Reflect.get(listener, kBoundListener2), + options + ); + } + /** + * Remove the listener for the given event. + */ + removeEventListener(event, listener, options) { + this[kEmitter2].removeEventListener( + event, + Reflect.get(listener, kBoundListener2), + options + ); + } + /** + * Send data to the original WebSocket server. + * @example + * server.send('hello') + * server.send(new Blob(['hello'])) + * server.send(new TextEncoder().encode('hello')) + */ + send(data) { + this[kSend](data); + } + [(kEmitter2, kSend)](data) { + const { realWebSocket } = this; + invariant2( + realWebSocket, + 'Failed to call "server.send()" for "%s": the connection is not open. Did you forget to call "server.connect()"?', + this.client.url + ); + if (realWebSocket.readyState === WebSocket.CLOSING || realWebSocket.readyState === WebSocket.CLOSED) { + return; + } + if (realWebSocket.readyState === WebSocket.CONNECTING) { + realWebSocket.addEventListener( + "open", + () => { + realWebSocket.send(data); + }, + { once: true } + ); + return; + } + realWebSocket.send(data); + } + /** + * Close the actual server connection. + */ + close() { + const { realWebSocket } = this; + invariant2( + realWebSocket, + 'Failed to close server connection for "%s": the connection is not open. Did you forget to call "server.connect()"?', + this.client.url + ); + this.realCloseController.abort(); + if (realWebSocket.readyState === WebSocket.CLOSING || realWebSocket.readyState === WebSocket.CLOSED) { + return; + } + realWebSocket.close(); + queueMicrotask(() => { + this[kEmitter2].dispatchEvent( + bindEvent( + this.realWebSocket, + new CancelableCloseEvent("close", { + /** + * @note `server.close()` in the interceptor + * always results in clean closures. + */ + code: 1e3, + cancelable: true + }) + ) + ); + }); + } + handleIncomingMessage(event) { + const messageEvent = bindEvent( + event.target, + new CancelableMessageEvent("message", { + data: event.data, + origin: event.origin, + cancelable: true + }) + ); + this[kEmitter2].dispatchEvent(messageEvent); + if (!messageEvent.defaultPrevented) { + this.client.dispatchEvent( + bindEvent( + /** + * @note Bind the forwarded original server events + * to the mock WebSocket instance so it would + * dispatch them straight away. + */ + this.client, + // Clone the message event again to prevent + // the "already being dispatched" exception. + new MessageEvent("message", { + data: event.data, + origin: event.origin + }) + ) + ); + } + } + handleMockClose(_event) { + if (this.realWebSocket) { + this.realWebSocket.close(); + } + } + handleRealClose(event) { + this.mockCloseController.abort(); + const closeEvent = bindEvent( + this.realWebSocket, + new CancelableCloseEvent("close", { + code: event.code, + reason: event.reason, + wasClean: event.wasClean, + cancelable: true + }) + ); + this[kEmitter2].dispatchEvent(closeEvent); + if (!closeEvent.defaultPrevented) { + this.client[kClose](event.code, event.reason); + } + } +}; + +// src/interceptors/WebSocket/WebSocketClassTransport.ts +var WebSocketClassTransport = class extends EventTarget { + constructor(socket) { + super(); + this.socket = socket; + this.socket.addEventListener("close", (event) => { + this.dispatchEvent(bindEvent(this.socket, new CloseEvent("close", event))); + }); + this.socket[kOnSend] = (data) => { + this.dispatchEvent( + bindEvent( + this.socket, + // Dispatch this as cancelable because "client" connection + // re-creates this message event (cannot dispatch the same event). + new CancelableMessageEvent("outgoing", { + data, + origin: this.socket.url, + cancelable: true + }) + ) + ); + }; + } + addEventListener(type, callback, options) { + return super.addEventListener(type, callback, options); + } + dispatchEvent(event) { + return super.dispatchEvent(event); + } + send(data) { + queueMicrotask(() => { + if (this.socket.readyState === this.socket.CLOSING || this.socket.readyState === this.socket.CLOSED) { + return; + } + const dispatchEvent = () => { + this.socket.dispatchEvent( + bindEvent( + /** + * @note Setting this event's "target" to the + * WebSocket override instance is important. + * This way it can tell apart original incoming events + * (must be forwarded to the transport) from the + * mocked message events like the one below + * (must be dispatched on the client instance). + */ + this.socket, + new MessageEvent("message", { + data, + origin: this.socket.url + }) + ) + ); + }; + if (this.socket.readyState === this.socket.CONNECTING) { + this.socket.addEventListener( + "open", + () => { + dispatchEvent(); + }, + { once: true } + ); + } else { + dispatchEvent(); + } + }); + } + close(code, reason) { + this.socket[kClose](code, reason); + } +}; + +// src/interceptors/WebSocket/index.ts +var _WebSocketInterceptor = class extends Interceptor { + constructor() { + super(_WebSocketInterceptor.symbol); + } + checkEnvironment() { + return hasConfigurableGlobal("WebSocket"); + } + setup() { + const originalWebSocketDescriptor = Object.getOwnPropertyDescriptor( + globalThis, + "WebSocket" + ); + const WebSocketProxy = new Proxy(globalThis.WebSocket, { + construct: (target, args, newTarget) => { + const [url, protocols] = args; + const createConnection = () => { + return Reflect.construct(target, args, newTarget); + }; + const socket = new WebSocketOverride(url, protocols); + const transport = new WebSocketClassTransport(socket); + queueMicrotask(() => { + try { + const server = new WebSocketServerConnection( + socket, + transport, + createConnection + ); + const hasConnectionListeners = this.emitter.emit("connection", { + client: new WebSocketClientConnection(socket, transport), + server, + info: { + protocols + } + }); + if (hasConnectionListeners) { + socket[kPassthroughPromise].resolve(false); + } else { + socket[kPassthroughPromise].resolve(true); + server.connect(); + server.addEventListener("open", () => { + socket.dispatchEvent(bindEvent(socket, new Event("open"))); + if (server["realWebSocket"]) { + socket.protocol = server["realWebSocket"].protocol; + } + }); + } + } catch (error) { + if (error instanceof Error) { + socket.dispatchEvent(new Event("error")); + if (socket.readyState !== WebSocket.CLOSING && socket.readyState !== WebSocket.CLOSED) { + socket[kClose](1011, error.message, false); + } + console.error(error); + } + } + }); + return socket; + } + }); + Object.defineProperty(globalThis, "WebSocket", { + value: WebSocketProxy, + configurable: true + }); + this.subscriptions.push(() => { + Object.defineProperty( + globalThis, + "WebSocket", + originalWebSocketDescriptor + ); + }); + } +}; +var WebSocketInterceptor = _WebSocketInterceptor; +WebSocketInterceptor.symbol = Symbol("websocket"); +export { + WebSocketClientConnection, + WebSocketInterceptor, + WebSocketServerConnection +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.mjs.map new file mode 100644 index 0000000000..328d20569d --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/WebSocket/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../../../src/interceptors/WebSocket/utils/bindEvent.ts","../../../../src/interceptors/WebSocket/utils/events.ts","../../../../src/interceptors/WebSocket/WebSocketClientConnection.ts","../../../../src/interceptors/WebSocket/WebSocketServerConnection.ts","../../../../src/interceptors/WebSocket/WebSocketOverride.ts","../../../../src/interceptors/WebSocket/WebSocketClassTransport.ts","../../../../src/interceptors/WebSocket/index.ts"],"sourcesContent":["type EventWithTarget = E & { target: T }\n\nexport function bindEvent(\n target: T,\n event: E\n): EventWithTarget {\n Object.defineProperties(event, {\n target: {\n value: target,\n enumerable: true,\n writable: true,\n },\n currentTarget: {\n value: target,\n enumerable: true,\n writable: true,\n },\n })\n\n return event as EventWithTarget\n}\n","const kCancelable = Symbol('kCancelable')\nconst kDefaultPrevented = Symbol('kDefaultPrevented')\n\n/**\n * A `MessageEvent` superset that supports event cancellation\n * in Node.js. It's rather non-intrusive so it can be safely\n * used in the browser as well.\n *\n * @see https://github.com/nodejs/node/issues/51767\n */\nexport class CancelableMessageEvent extends MessageEvent {\n [kCancelable]: boolean;\n [kDefaultPrevented]: boolean\n\n constructor(type: string, init: MessageEventInit) {\n super(type, init)\n this[kCancelable] = !!init.cancelable\n this[kDefaultPrevented] = false\n }\n\n get cancelable() {\n return this[kCancelable]\n }\n\n set cancelable(nextCancelable) {\n this[kCancelable] = nextCancelable\n }\n\n get defaultPrevented() {\n return this[kDefaultPrevented]\n }\n\n set defaultPrevented(nextDefaultPrevented) {\n this[kDefaultPrevented] = nextDefaultPrevented\n }\n\n public preventDefault(): void {\n if (this.cancelable && !this[kDefaultPrevented]) {\n this[kDefaultPrevented] = true\n }\n }\n}\n\ninterface CloseEventInit extends EventInit {\n code?: number\n reason?: string\n wasClean?: boolean\n}\n\nexport class CloseEvent extends Event {\n public code: number\n public reason: string\n public wasClean: boolean\n\n constructor(type: string, init: CloseEventInit = {}) {\n super(type, init)\n this.code = init.code === undefined ? 0 : init.code\n this.reason = init.reason === undefined ? '' : init.reason\n this.wasClean = init.wasClean === undefined ? false : init.wasClean\n }\n}\n\nexport class CancelableCloseEvent extends CloseEvent {\n [kCancelable]: boolean;\n [kDefaultPrevented]: boolean\n\n constructor(type: string, init: CloseEventInit = {}) {\n super(type, init)\n this[kCancelable] = !!init.cancelable\n this[kDefaultPrevented] = false\n }\n\n get cancelable() {\n return this[kCancelable]\n }\n\n set cancelable(nextCancelable) {\n this[kCancelable] = nextCancelable\n }\n\n get defaultPrevented() {\n return this[kDefaultPrevented]\n }\n\n set defaultPrevented(nextDefaultPrevented) {\n this[kDefaultPrevented] = nextDefaultPrevented\n }\n\n public preventDefault(): void {\n if (this.cancelable && !this[kDefaultPrevented]) {\n this[kDefaultPrevented] = true\n }\n }\n}\n","import type { WebSocketData, WebSocketTransport } from './WebSocketTransport'\nimport type { WebSocketEventListener } from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\nimport { createRequestId } from '../../createRequestId'\n\nconst kEmitter = Symbol('kEmitter')\nconst kBoundListener = Symbol('kBoundListener')\n\ninterface WebSocketClientEventMap {\n message: MessageEvent\n close: CloseEvent\n}\n\nexport interface WebSocketClientConnectionProtocol {\n id: string\n url: URL\n send(data: WebSocketData): void\n close(code?: number, reason?: string): void\n}\n\n/**\n * The WebSocket client instance represents an incoming\n * client connection. The user can control the connection,\n * send and receive events.\n */\nexport class WebSocketClientConnection\n implements WebSocketClientConnectionProtocol\n{\n public readonly id: string\n public readonly url: URL\n\n private [kEmitter]: EventTarget\n\n constructor(\n public readonly socket: WebSocket,\n private readonly transport: WebSocketTransport\n ) {\n this.id = createRequestId()\n this.url = new URL(socket.url)\n this[kEmitter] = new EventTarget()\n\n // Emit outgoing client data (\"ws.send()\") as \"message\"\n // events on the \"client\" connection.\n this.transport.addEventListener('outgoing', (event) => {\n const message = bindEvent(\n this.socket,\n new CancelableMessageEvent('message', {\n data: event.data,\n origin: event.origin,\n cancelable: true,\n })\n )\n\n this[kEmitter].dispatchEvent(message)\n\n // This is a bit silly but forward the cancellation state\n // of the \"client\" message event to the \"outgoing\" transport event.\n // This way, other agens (like \"server\" connection) can know\n // whether the client listener has pervented the default.\n if (message.defaultPrevented) {\n event.preventDefault()\n }\n })\n\n /**\n * Emit the \"close\" event on the \"client\" connection\n * whenever the underlying transport is closed.\n * @note \"client.close()\" does NOT dispatch the \"close\"\n * event on the WebSocket because it uses non-configurable\n * close status code. Thus, we listen to the transport\n * instead of the WebSocket's \"close\" event.\n */\n this.transport.addEventListener('close', (event) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.socket, new CloseEvent('close', event))\n )\n })\n }\n\n /**\n * Listen for the outgoing events from the connected WebSocket client.\n */\n public addEventListener(\n type: EventType,\n listener: WebSocketEventListener,\n options?: AddEventListenerOptions | boolean\n ): void {\n if (!Reflect.has(listener, kBoundListener)) {\n const boundListener = listener.bind(this.socket)\n\n // Store the bound listener on the original listener\n // so the exact bound function can be accessed in \"removeEventListener()\".\n Object.defineProperty(listener, kBoundListener, {\n value: boundListener,\n enumerable: false,\n configurable: false,\n })\n }\n\n this[kEmitter].addEventListener(\n type,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Removes the listener for the given event.\n */\n public removeEventListener(\n event: EventType,\n listener: WebSocketEventListener,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Send data to the connected client.\n */\n public send(data: WebSocketData): void {\n this.transport.send(data)\n }\n\n /**\n * Close the WebSocket connection.\n * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1).\n * @param {string} reason A custom connection close reason.\n */\n public close(code?: number, reason?: string): void {\n this.transport.close(code, reason)\n }\n}\n","import { invariant } from 'outvariant'\nimport {\n kClose,\n WebSocketEventListener,\n WebSocketOverride,\n} from './WebSocketOverride'\nimport type { WebSocketData } from './WebSocketTransport'\nimport type { WebSocketClassTransport } from './WebSocketClassTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport {\n CancelableMessageEvent,\n CancelableCloseEvent,\n CloseEvent,\n} from './utils/events'\n\nconst kEmitter = Symbol('kEmitter')\nconst kBoundListener = Symbol('kBoundListener')\nconst kSend = Symbol('kSend')\n\ninterface WebSocketServerEventMap {\n open: Event\n message: MessageEvent\n error: Event\n close: CloseEvent\n}\n\n/**\n * The WebSocket server instance represents the actual production\n * WebSocket server connection. It's idle by default but you can\n * establish it by calling `server.connect()`.\n */\nexport class WebSocketServerConnection {\n /**\n * A WebSocket instance connected to the original server.\n */\n private realWebSocket?: WebSocket\n private mockCloseController: AbortController\n private realCloseController: AbortController\n private [kEmitter]: EventTarget\n\n constructor(\n private readonly client: WebSocketOverride,\n private readonly transport: WebSocketClassTransport,\n private readonly createConnection: () => WebSocket\n ) {\n this[kEmitter] = new EventTarget()\n this.mockCloseController = new AbortController()\n this.realCloseController = new AbortController()\n\n // Automatically forward outgoing client events\n // to the actual server unless the outgoing message event\n // has been prevented. The \"outgoing\" transport event it\n // dispatched by the \"client\" connection.\n this.transport.addEventListener('outgoing', (event) => {\n // Ignore client messages if the server connection\n // hasn't been established yet. Nowhere to forward.\n if (typeof this.realWebSocket === 'undefined') {\n return\n }\n\n // Every outgoing client message can prevent this forwarding\n // by preventing the default of the outgoing message event.\n // This listener will be added before user-defined listeners,\n // so execute the logic on the next tick.\n queueMicrotask(() => {\n if (!event.defaultPrevented) {\n /**\n * @note Use the internal send mechanism so consumers can tell\n * apart direct user calls to `server.send()` and internal calls.\n * E.g. MSW has to ignore this internal call to log out messages correctly.\n */\n this[kSend](event.data)\n }\n })\n })\n\n this.transport.addEventListener(\n 'incoming',\n this.handleIncomingMessage.bind(this)\n )\n }\n\n /**\n * The `WebSocket` instance connected to the original server.\n * Accessing this before calling `server.connect()` will throw.\n */\n public get socket(): WebSocket {\n invariant(\n this.realWebSocket,\n 'Cannot access \"socket\" on the original WebSocket server object: the connection is not open. Did you forget to call `server.connect()`?'\n )\n\n return this.realWebSocket\n }\n\n /**\n * Open connection to the original WebSocket server.\n */\n public connect(): void {\n invariant(\n !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN,\n 'Failed to call \"connect()\" on the original WebSocket instance: the connection already open'\n )\n\n const realWebSocket = this.createConnection()\n\n // Inherit the binary type from the mock WebSocket client.\n realWebSocket.binaryType = this.client.binaryType\n\n // Allow the interceptor to listen to when the server connection\n // has been established. This isn't necessary to operate with the connection\n // but may be beneficial in some cases (like conditionally adding logging).\n realWebSocket.addEventListener(\n 'open',\n (event) => {\n this[kEmitter].dispatchEvent(\n bindEvent(this.realWebSocket!, new Event('open', event))\n )\n },\n { once: true }\n )\n\n realWebSocket.addEventListener('message', (event) => {\n // Dispatch the \"incoming\" transport event instead of\n // invoking the internal handler directly. This way,\n // anyone can listen to the \"incoming\" event but this\n // class is the one resulting in it.\n this.transport.dispatchEvent(\n bindEvent(\n this.realWebSocket!,\n new MessageEvent('incoming', {\n data: event.data,\n origin: event.origin,\n })\n )\n )\n })\n\n // Close the original connection when the mock client closes.\n // E.g. \"client.close()\" was called. This is never forwarded anywhere.\n this.client.addEventListener(\n 'close',\n (event) => {\n this.handleMockClose(event)\n },\n {\n signal: this.mockCloseController.signal,\n }\n )\n\n // Forward the \"close\" event to let the interceptor handle\n // closures initiated by the original server.\n realWebSocket.addEventListener(\n 'close',\n (event) => {\n this.handleRealClose(event)\n },\n {\n signal: this.realCloseController.signal,\n }\n )\n\n realWebSocket.addEventListener('error', () => {\n const errorEvent = bindEvent(\n realWebSocket,\n new Event('error', { cancelable: true })\n )\n\n // Emit the \"error\" event on the `server` connection\n // to let the interceptor react to original server errors.\n this[kEmitter].dispatchEvent(errorEvent)\n\n // If the error event from the original server hasn't been prevented,\n // forward it to the underlying client.\n if (!errorEvent.defaultPrevented) {\n this.client.dispatchEvent(bindEvent(this.client, new Event('error')))\n }\n })\n\n this.realWebSocket = realWebSocket\n }\n\n /**\n * Listen for the incoming events from the original WebSocket server.\n */\n public addEventListener(\n event: EventType,\n listener: WebSocketEventListener,\n options?: AddEventListenerOptions | boolean\n ): void {\n if (!Reflect.has(listener, kBoundListener)) {\n const boundListener = listener.bind(this.client)\n\n // Store the bound listener on the original listener\n // so the exact bound function can be accessed in \"removeEventListener()\".\n Object.defineProperty(listener, kBoundListener, {\n value: boundListener,\n enumerable: false,\n })\n }\n\n this[kEmitter].addEventListener(\n event,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Remove the listener for the given event.\n */\n public removeEventListener(\n event: EventType,\n listener: WebSocketEventListener,\n options?: EventListenerOptions | boolean\n ): void {\n this[kEmitter].removeEventListener(\n event,\n Reflect.get(listener, kBoundListener) as EventListener,\n options\n )\n }\n\n /**\n * Send data to the original WebSocket server.\n * @example\n * server.send('hello')\n * server.send(new Blob(['hello']))\n * server.send(new TextEncoder().encode('hello'))\n */\n public send(data: WebSocketData): void {\n this[kSend](data)\n }\n\n private [kSend](data: WebSocketData): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to call \"server.send()\" for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.client.url\n )\n\n // Silently ignore writes on the closed original WebSocket.\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n // Delegate the send to when the original connection is open.\n // Unlike the mock, connecting to the original server may take time\n // so we cannot call this on the next tick.\n if (realWebSocket.readyState === WebSocket.CONNECTING) {\n realWebSocket.addEventListener(\n 'open',\n () => {\n realWebSocket.send(data)\n },\n { once: true }\n )\n return\n }\n\n // Send the data to the original WebSocket server.\n realWebSocket.send(data)\n }\n\n /**\n * Close the actual server connection.\n */\n public close(): void {\n const { realWebSocket } = this\n\n invariant(\n realWebSocket,\n 'Failed to close server connection for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n this.client.url\n )\n\n // Remove the \"close\" event listener from the server\n // so it doesn't close the underlying WebSocket client\n // when you call \"server.close()\". This also prevents the\n // `close` event on the `server` connection from being dispatched twice.\n this.realCloseController.abort()\n\n if (\n realWebSocket.readyState === WebSocket.CLOSING ||\n realWebSocket.readyState === WebSocket.CLOSED\n ) {\n return\n }\n\n // Close the actual client connection.\n realWebSocket.close()\n\n // Dispatch the \"close\" event on the `server` connection.\n queueMicrotask(() => {\n this[kEmitter].dispatchEvent(\n bindEvent(\n this.realWebSocket,\n new CancelableCloseEvent('close', {\n /**\n * @note `server.close()` in the interceptor\n * always results in clean closures.\n */\n code: 1000,\n cancelable: true,\n })\n )\n )\n })\n }\n\n private handleIncomingMessage(event: MessageEvent): void {\n // Clone the event to dispatch it on this class\n // once again and prevent the \"already being dispatched\"\n // exception. Clone it here so we can observe this event\n // being prevented in the \"server.on()\" listeners.\n const messageEvent = bindEvent(\n event.target,\n new CancelableMessageEvent('message', {\n data: event.data,\n origin: event.origin,\n cancelable: true,\n })\n )\n\n /**\n * @note Emit \"message\" event on the server connection\n * instance to let the interceptor know about these\n * incoming events from the original server. In that listener,\n * the interceptor can modify or skip the event forwarding\n * to the mock WebSocket instance.\n */\n this[kEmitter].dispatchEvent(messageEvent)\n\n /**\n * @note Forward the incoming server events to the client.\n * Preventing the default on the message event stops this.\n */\n if (!messageEvent.defaultPrevented) {\n this.client.dispatchEvent(\n bindEvent(\n /**\n * @note Bind the forwarded original server events\n * to the mock WebSocket instance so it would\n * dispatch them straight away.\n */\n this.client,\n // Clone the message event again to prevent\n // the \"already being dispatched\" exception.\n new MessageEvent('message', {\n data: event.data,\n origin: event.origin,\n })\n )\n )\n }\n }\n\n private handleMockClose(_event: Event): void {\n // Close the original connection if the mock client closes.\n if (this.realWebSocket) {\n this.realWebSocket.close()\n }\n }\n\n private handleRealClose(event: CloseEvent): void {\n // For closures originating from the original server,\n // remove the \"close\" listener from the mock client.\n // original close -> (?) client[kClose]() --X--> \"close\" (again).\n this.mockCloseController.abort()\n\n const closeEvent = bindEvent(\n this.realWebSocket,\n new CancelableCloseEvent('close', {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean,\n cancelable: true,\n })\n )\n\n this[kEmitter].dispatchEvent(closeEvent)\n\n // If the close event from the server hasn't been prevented,\n // forward the closure to the mock client.\n if (!closeEvent.defaultPrevented) {\n // Close the intercepted client forcefully to\n // allow non-configurable status codes from the server.\n // If the socket has been closed by now, no harm calling\n // this again—it will have no effect.\n this.client[kClose](event.code, event.reason)\n }\n }\n}\n","import { invariant } from 'outvariant'\nimport type { WebSocketData } from './WebSocketTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport { CloseEvent } from './utils/events'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\n\nexport type WebSocketEventListener<\n EventType extends WebSocketEventMap[keyof WebSocketEventMap] = Event\n> = (this: WebSocket, event: EventType) => void\n\nconst WEBSOCKET_CLOSE_CODE_RANGE_ERROR =\n 'InvalidAccessError: close code out of user configurable range'\n\nexport const kPassthroughPromise = Symbol('kPassthroughPromise')\nexport const kOnSend = Symbol('kOnSend')\nexport const kClose = Symbol('kClose')\n\nexport class WebSocketOverride extends EventTarget implements WebSocket {\n static readonly CONNECTING = 0\n static readonly OPEN = 1\n static readonly CLOSING = 2\n static readonly CLOSED = 3\n readonly CONNECTING = 0\n readonly OPEN = 1\n readonly CLOSING = 2\n readonly CLOSED = 3\n\n public url: string\n public protocol: string\n public extensions: string\n public binaryType: BinaryType\n public readyState: number\n public bufferedAmount: number\n\n private _onopen: WebSocketEventListener | null = null\n private _onmessage: WebSocketEventListener<\n MessageEvent\n > | null = null\n private _onerror: WebSocketEventListener | null = null\n private _onclose: WebSocketEventListener | null = null\n\n private [kPassthroughPromise]: DeferredPromise\n private [kOnSend]?: (data: WebSocketData) => void\n\n constructor(url: string | URL, protocols?: string | Array) {\n super()\n this.url = url.toString()\n this.protocol = ''\n this.extensions = ''\n this.binaryType = 'blob'\n this.readyState = this.CONNECTING\n this.bufferedAmount = 0\n\n this[kPassthroughPromise] = new DeferredPromise()\n\n queueMicrotask(async () => {\n if (await this[kPassthroughPromise]) {\n return\n }\n\n this.protocol =\n typeof protocols === 'string'\n ? protocols\n : Array.isArray(protocols) && protocols.length > 0\n ? protocols[0]\n : ''\n\n /**\n * @note Check that nothing has prevented this connection\n * (e.g. called `client.close()` in the connection listener).\n * If the connection has been prevented, never dispatch the open event,.\n */\n if (this.readyState === this.CONNECTING) {\n this.readyState = this.OPEN\n this.dispatchEvent(bindEvent(this, new Event('open')))\n }\n })\n }\n\n set onopen(listener: WebSocketEventListener | null) {\n this.removeEventListener('open', this._onopen)\n this._onopen = listener\n if (listener !== null) {\n this.addEventListener('open', listener)\n }\n }\n get onopen(): WebSocketEventListener | null {\n return this._onopen\n }\n\n set onmessage(\n listener: WebSocketEventListener> | null\n ) {\n this.removeEventListener(\n 'message',\n this._onmessage as WebSocketEventListener\n )\n this._onmessage = listener\n if (listener !== null) {\n this.addEventListener('message', listener)\n }\n }\n get onmessage(): WebSocketEventListener> | null {\n return this._onmessage\n }\n\n set onerror(listener: WebSocketEventListener | null) {\n this.removeEventListener('error', this._onerror)\n this._onerror = listener\n if (listener !== null) {\n this.addEventListener('error', listener)\n }\n }\n get onerror(): WebSocketEventListener | null {\n return this._onerror\n }\n\n set onclose(listener: WebSocketEventListener | null) {\n this.removeEventListener('close', this._onclose as WebSocketEventListener)\n this._onclose = listener\n if (listener !== null) {\n this.addEventListener('close', listener)\n }\n }\n get onclose(): WebSocketEventListener | null {\n return this._onclose\n }\n\n /**\n * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0\n */\n public send(data: WebSocketData): void {\n if (this.readyState === this.CONNECTING) {\n this.close()\n throw new DOMException('InvalidStateError')\n }\n\n // Sending when the socket is about to close\n // discards the sent data.\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n // Buffer the data to send in this even loop\n // but send it in the next.\n this.bufferedAmount += getDataSize(data)\n\n queueMicrotask(() => {\n // This is a bit optimistic but since no actual data transfer\n // is involved, all the data will be \"sent\" on the next tick.\n this.bufferedAmount = 0\n\n /**\n * @note Notify the parent about outgoing data.\n * This notifies the transport and the connection\n * listens to the outgoing data to emit the \"message\" event.\n */\n this[kOnSend]?.(data)\n })\n }\n\n public close(code: number = 1000, reason?: string): void {\n invariant(code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR)\n invariant(\n code === 1000 || (code >= 3000 && code <= 4999),\n WEBSOCKET_CLOSE_CODE_RANGE_ERROR\n )\n\n this[kClose](code, reason)\n }\n\n private [kClose](\n code: number = 1000,\n reason?: string,\n wasClean = true\n ): void {\n /**\n * @note Move this check here so that even internall closures,\n * like those triggered by the `server` connection, are not\n * performed twice.\n */\n if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n return\n }\n\n this.readyState = this.CLOSING\n\n queueMicrotask(() => {\n this.readyState = this.CLOSED\n\n this.dispatchEvent(\n bindEvent(\n this,\n new CloseEvent('close', {\n code,\n reason,\n wasClean,\n })\n )\n )\n\n // Remove all event listeners once the socket is closed.\n this._onopen = null\n this._onmessage = null\n this._onerror = null\n this._onclose = null\n })\n }\n\n public addEventListener(\n type: K,\n listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions\n ): void\n public addEventListener(\n type: unknown,\n listener: unknown,\n options?: unknown\n ): void {\n return super.addEventListener(\n type as string,\n listener as EventListener,\n options as AddEventListenerOptions\n )\n }\n\n removeEventListener(\n type: K,\n callback: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void {\n return super.removeEventListener(type, callback, options)\n }\n}\n\nfunction getDataSize(data: WebSocketData): number {\n if (typeof data === 'string') {\n return data.length\n }\n\n if (data instanceof Blob) {\n return data.size\n }\n\n return data.byteLength\n}\n","import { bindEvent } from './utils/bindEvent'\nimport {\n StrictEventListenerOrEventListenerObject,\n WebSocketData,\n WebSocketTransport,\n WebSocketTransportEventMap,\n} from './WebSocketTransport'\nimport { kOnSend, kClose, WebSocketOverride } from './WebSocketOverride'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\n\n/**\n * Abstraction over the given mock `WebSocket` instance that allows\n * for controlling that instance (e.g. sending and receiving messages).\n */\nexport class WebSocketClassTransport\n extends EventTarget\n implements WebSocketTransport\n{\n constructor(protected readonly socket: WebSocketOverride) {\n super()\n\n // Emit the \"close\" event on the transport if the close\n // originates from the WebSocket client. E.g. the application\n // calls \"ws.close()\", not the interceptor.\n this.socket.addEventListener('close', (event) => {\n this.dispatchEvent(bindEvent(this.socket, new CloseEvent('close', event)))\n })\n\n /**\n * Emit the \"outgoing\" event on the transport\n * whenever the WebSocket client sends data (\"ws.send()\").\n */\n this.socket[kOnSend] = (data) => {\n this.dispatchEvent(\n bindEvent(\n this.socket,\n // Dispatch this as cancelable because \"client\" connection\n // re-creates this message event (cannot dispatch the same event).\n new CancelableMessageEvent('outgoing', {\n data,\n origin: this.socket.url,\n cancelable: true,\n })\n )\n )\n }\n }\n\n public addEventListener(\n type: EventType,\n callback: StrictEventListenerOrEventListenerObject<\n WebSocketTransportEventMap[EventType]\n > | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n return super.addEventListener(type, callback as EventListener, options)\n }\n\n public dispatchEvent(\n event: WebSocketTransportEventMap[EventType]\n ): boolean {\n return super.dispatchEvent(event)\n }\n\n public send(data: WebSocketData): void {\n queueMicrotask(() => {\n if (\n this.socket.readyState === this.socket.CLOSING ||\n this.socket.readyState === this.socket.CLOSED\n ) {\n return\n }\n\n const dispatchEvent = () => {\n this.socket.dispatchEvent(\n bindEvent(\n /**\n * @note Setting this event's \"target\" to the\n * WebSocket override instance is important.\n * This way it can tell apart original incoming events\n * (must be forwarded to the transport) from the\n * mocked message events like the one below\n * (must be dispatched on the client instance).\n */\n this.socket,\n new MessageEvent('message', {\n data,\n origin: this.socket.url,\n })\n )\n )\n }\n\n if (this.socket.readyState === this.socket.CONNECTING) {\n this.socket.addEventListener(\n 'open',\n () => {\n dispatchEvent()\n },\n { once: true }\n )\n } else {\n dispatchEvent()\n }\n })\n }\n\n public close(code: number, reason?: string): void {\n /**\n * @note Call the internal close method directly\n * to allow closing the connection with the status codes\n * that are non-configurable by the user (> 1000 <= 1015).\n */\n this.socket[kClose](code, reason)\n }\n}\n","import { Interceptor } from '../../Interceptor'\nimport {\n type WebSocketClientConnectionProtocol,\n WebSocketClientConnection,\n} from './WebSocketClientConnection'\nimport { WebSocketServerConnection } from './WebSocketServerConnection'\nimport { WebSocketClassTransport } from './WebSocketClassTransport'\nimport {\n kClose,\n kPassthroughPromise,\n WebSocketOverride,\n} from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\n\nexport { type WebSocketData, WebSocketTransport } from './WebSocketTransport'\nexport {\n WebSocketClientConnection,\n WebSocketClientConnectionProtocol,\n WebSocketServerConnection,\n}\n\nexport type WebSocketEventMap = {\n connection: [args: WebSocketConnectionData]\n}\n\nexport type WebSocketConnectionData = {\n /**\n * The incoming WebSocket client connection.\n */\n client: WebSocketClientConnection\n\n /**\n * The original WebSocket server connection.\n */\n server: WebSocketServerConnection\n\n /**\n * The connection information.\n */\n info: {\n /**\n * The protocols supported by the WebSocket client.\n */\n protocols: string | Array | undefined\n }\n}\n\n/**\n * Intercept the outgoing WebSocket connections created using\n * the global `WebSocket` class.\n */\nexport class WebSocketInterceptor extends Interceptor {\n static symbol = Symbol('websocket')\n\n constructor() {\n super(WebSocketInterceptor.symbol)\n }\n\n protected checkEnvironment(): boolean {\n return hasConfigurableGlobal('WebSocket')\n }\n\n protected setup(): void {\n const originalWebSocketDescriptor = Object.getOwnPropertyDescriptor(\n globalThis,\n 'WebSocket'\n )\n\n const WebSocketProxy = new Proxy(globalThis.WebSocket, {\n construct: (\n target,\n args: ConstructorParameters,\n newTarget\n ) => {\n const [url, protocols] = args\n\n const createConnection = (): WebSocket => {\n return Reflect.construct(target, args, newTarget)\n }\n\n // All WebSocket instances are mocked and don't forward\n // any events to the original server (no connection established).\n // To forward the events, the user must use the \"server.send()\" API.\n const socket = new WebSocketOverride(url, protocols)\n const transport = new WebSocketClassTransport(socket)\n\n // Emit the \"connection\" event to the interceptor on the next tick\n // so the client can modify WebSocket options, like \"binaryType\"\n // while the connection is already pending.\n queueMicrotask(() => {\n try {\n const server = new WebSocketServerConnection(\n socket,\n transport,\n createConnection\n )\n\n // The \"globalThis.WebSocket\" class stands for\n // the client-side connection. Assume it's established\n // as soon as the WebSocket instance is constructed.\n const hasConnectionListeners = this.emitter.emit('connection', {\n client: new WebSocketClientConnection(socket, transport),\n server,\n info: {\n protocols,\n },\n })\n\n if (hasConnectionListeners) {\n socket[kPassthroughPromise].resolve(false)\n } else {\n socket[kPassthroughPromise].resolve(true)\n\n server.connect()\n\n // Forward the \"open\" event from the original server\n // to the mock WebSocket client in the case of a passthrough connection.\n server.addEventListener('open', () => {\n socket.dispatchEvent(bindEvent(socket, new Event('open')))\n\n // Forward the original connection protocol to the\n // mock WebSocket client.\n if (server['realWebSocket']) {\n socket.protocol = server['realWebSocket'].protocol\n }\n })\n }\n } catch (error) {\n /**\n * @note Translate unhandled exceptions during the connection\n * handling (i.e. interceptor exceptions) as WebSocket connection\n * closures with error. This prevents from the exceptions occurring\n * in `queueMicrotask` from being process-wide and uncatchable.\n */\n if (error instanceof Error) {\n socket.dispatchEvent(new Event('error'))\n\n // No need to close the connection if it's already being closed.\n // E.g. the interceptor called `client.close()` and then threw an error.\n if (\n socket.readyState !== WebSocket.CLOSING &&\n socket.readyState !== WebSocket.CLOSED\n ) {\n socket[kClose](1011, error.message, false)\n }\n\n console.error(error)\n }\n }\n })\n\n return socket\n },\n })\n\n Object.defineProperty(globalThis, 'WebSocket', {\n value: WebSocketProxy,\n configurable: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(\n globalThis,\n 'WebSocket',\n originalWebSocketDescriptor!\n )\n })\n }\n}\n"],"mappings":"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","names":["invariant","kEmitter","kBoundListener","invariant"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.d.ts b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.d.ts new file mode 100644 index 0000000000..477a2a659c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.d.ts @@ -0,0 +1,15 @@ +import { Emitter } from 'strict-event-emitter'; +import { H as HttpRequestEventMap } from '../../glossary-6564c252.js'; +import { I as Interceptor } from '../../Interceptor-af98b768.js'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; + +type XMLHttpRequestEmitter = Emitter; +declare class XMLHttpRequestInterceptor extends Interceptor { + static interceptorSymbol: symbol; + constructor(); + protected checkEnvironment(): boolean; + protected setup(): void; +} + +export { XMLHttpRequestEmitter, XMLHttpRequestInterceptor }; diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.js b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.js new file mode 100644 index 0000000000..4ff356c93d --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.js @@ -0,0 +1,12 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkZIT2QX7Djs = require('../../chunk-ZIT2QX7D.js'); +require('../../chunk-LK6DILFK.js'); +require('../../chunk-FGSEOIC4.js'); +require('../../chunk-BC2BLJQN.js'); +require('../../chunk-PFGO5BSM.js'); +require('../../chunk-TIPR373R.js'); + + +exports.XMLHttpRequestInterceptor = _chunkZIT2QX7Djs.XMLHttpRequestInterceptor; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.js.map b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.js.map new file mode 100644 index 0000000000..a464c6732e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.mjs b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.mjs new file mode 100644 index 0000000000..f2d02410cb --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.mjs @@ -0,0 +1,12 @@ +import { + XMLHttpRequestInterceptor +} from "../../chunk-DODHRDV6.mjs"; +import "../../chunk-6HYIRFX2.mjs"; +import "../../chunk-H5O73WD2.mjs"; +import "../../chunk-5UK33FSU.mjs"; +import "../../chunk-TX5GBTFY.mjs"; +import "../../chunk-QED3Q6Z2.mjs"; +export { + XMLHttpRequestInterceptor +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.mjs.map new file mode 100644 index 0000000000..84c51b288c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/XMLHttpRequest/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.d.ts b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.d.ts new file mode 100644 index 0000000000..ef276846a8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.d.ts @@ -0,0 +1,14 @@ +import { H as HttpRequestEventMap } from '../../glossary-6564c252.js'; +import { I as Interceptor } from '../../Interceptor-af98b768.js'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; +import 'strict-event-emitter'; + +declare class FetchInterceptor extends Interceptor { + static symbol: symbol; + constructor(); + protected checkEnvironment(): boolean; + protected setup(): Promise; +} + +export { FetchInterceptor }; diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.js b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.js new file mode 100644 index 0000000000..00603361cb --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.js @@ -0,0 +1,11 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkQVOTKFTBjs = require('../../chunk-QVOTKFTB.js'); +require('../../chunk-FGSEOIC4.js'); +require('../../chunk-BC2BLJQN.js'); +require('../../chunk-PFGO5BSM.js'); +require('../../chunk-TIPR373R.js'); + + +exports.FetchInterceptor = _chunkQVOTKFTBjs.FetchInterceptor; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.js.map b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.js.map new file mode 100644 index 0000000000..a464c6732e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.mjs b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.mjs new file mode 100644 index 0000000000..a8673043d5 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.mjs @@ -0,0 +1,11 @@ +import { + FetchInterceptor +} from "../../chunk-XTX2SIN6.mjs"; +import "../../chunk-H5O73WD2.mjs"; +import "../../chunk-5UK33FSU.mjs"; +import "../../chunk-TX5GBTFY.mjs"; +import "../../chunk-QED3Q6Z2.mjs"; +export { + FetchInterceptor +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.mjs.map new file mode 100644 index 0000000000..84c51b288c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/interceptors/fetch/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/presets/browser.d.ts b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.d.ts new file mode 100644 index 0000000000..fb4d2e49fb --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.d.ts @@ -0,0 +1,15 @@ +import { FetchInterceptor } from '../interceptors/fetch/index.js'; +import { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest/index.js'; +import '../glossary-6564c252.js'; +import '@open-draft/deferred-promise'; +import '../Interceptor-af98b768.js'; +import '@open-draft/logger'; +import 'strict-event-emitter'; + +/** + * The default preset provisions the interception of requests + * regardless of their type (fetch/XMLHttpRequest). + */ +declare const _default: readonly [FetchInterceptor, XMLHttpRequestInterceptor]; + +export { _default as default }; diff --git a/node_modules/@mswjs/interceptors/lib/browser/presets/browser.js b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.js new file mode 100644 index 0000000000..e3b183fa34 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.js @@ -0,0 +1,21 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkZIT2QX7Djs = require('../chunk-ZIT2QX7D.js'); +require('../chunk-LK6DILFK.js'); + + +var _chunkQVOTKFTBjs = require('../chunk-QVOTKFTB.js'); +require('../chunk-FGSEOIC4.js'); +require('../chunk-BC2BLJQN.js'); +require('../chunk-PFGO5BSM.js'); +require('../chunk-TIPR373R.js'); + +// src/presets/browser.ts +var browser_default = [ + new (0, _chunkQVOTKFTBjs.FetchInterceptor)(), + new (0, _chunkZIT2QX7Djs.XMLHttpRequestInterceptor)() +]; + + +exports.default = browser_default; +//# sourceMappingURL=browser.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/presets/browser.js.map b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.js.map new file mode 100644 index 0000000000..fc2cb3d5d7 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../../src/presets/browser.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAOA,IAAO,kBAAQ;AAAA,EACb,IAAI,iBAAiB;AAAA,EACrB,IAAI,0BAA0B;AAChC","sourcesContent":["import { FetchInterceptor } from '../interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest'\n\n/**\n * The default preset provisions the interception of requests\n * regardless of their type (fetch/XMLHttpRequest).\n */\nexport default [\n new FetchInterceptor(),\n new XMLHttpRequestInterceptor(),\n] as const\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/presets/browser.mjs b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.mjs new file mode 100644 index 0000000000..33ea87b522 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.mjs @@ -0,0 +1,21 @@ +import { + XMLHttpRequestInterceptor +} from "../chunk-DODHRDV6.mjs"; +import "../chunk-6HYIRFX2.mjs"; +import { + FetchInterceptor +} from "../chunk-XTX2SIN6.mjs"; +import "../chunk-H5O73WD2.mjs"; +import "../chunk-5UK33FSU.mjs"; +import "../chunk-TX5GBTFY.mjs"; +import "../chunk-QED3Q6Z2.mjs"; + +// src/presets/browser.ts +var browser_default = [ + new FetchInterceptor(), + new XMLHttpRequestInterceptor() +]; +export { + browser_default as default +}; +//# sourceMappingURL=browser.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/browser/presets/browser.mjs.map b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.mjs.map new file mode 100644 index 0000000000..05ee5a1e59 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/browser/presets/browser.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../../src/presets/browser.ts"],"sourcesContent":["import { FetchInterceptor } from '../interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest'\n\n/**\n * The default preset provisions the interception of requests\n * regardless of their type (fetch/XMLHttpRequest).\n */\nexport default [\n new FetchInterceptor(),\n new XMLHttpRequestInterceptor(),\n] as const\n"],"mappings":";;;;;;;;;;;;;AAOA,IAAO,kBAAQ;AAAA,EACb,IAAI,iBAAiB;AAAA,EACrB,IAAI,0BAA0B;AAChC;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/BatchInterceptor-67bf41ba.d.ts b/node_modules/@mswjs/interceptors/lib/node/BatchInterceptor-67bf41ba.d.ts new file mode 100644 index 0000000000..b90f91bc9a --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/BatchInterceptor-67bf41ba.d.ts @@ -0,0 +1,24 @@ +import { EventMap, Listener } from 'strict-event-emitter'; +import { h as Interceptor, E as ExtractEventNames } from './Interceptor-436630be.js'; + +interface BatchInterceptorOptions>> { + name: string; + interceptors: InterceptorList; +} +type ExtractEventMapType>> = InterceptorList extends ReadonlyArray ? InterceptorType extends Interceptor ? EventMap : never : never; +/** + * A batch interceptor that exposes a single interface + * to apply and operate with multiple interceptors at once. + */ +declare class BatchInterceptor>, Events extends EventMap = ExtractEventMapType> extends Interceptor { + static symbol: symbol; + private interceptors; + constructor(options: BatchInterceptorOptions); + protected setup(): void; + on>(event: EventName, listener: Listener): this; + once>(event: EventName, listener: Listener): this; + off>(event: EventName, listener: Listener): this; + removeAllListeners>(event?: EventName | undefined): this; +} + +export { BatchInterceptorOptions as B, ExtractEventMapType as E, BatchInterceptor as a }; diff --git a/node_modules/@mswjs/interceptors/lib/node/Interceptor-436630be.d.ts b/node_modules/@mswjs/interceptors/lib/node/Interceptor-436630be.d.ts new file mode 100644 index 0000000000..08323b54c8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/Interceptor-436630be.d.ts @@ -0,0 +1,128 @@ +import { DeferredPromise } from '@open-draft/deferred-promise'; +import { Logger } from '@open-draft/logger'; +import { Emitter, Listener } from 'strict-event-emitter'; + +declare const kRequestHandled: unique symbol; +declare const kResponsePromise: unique symbol; +declare class RequestController { + private request; + /** + * Internal response promise. + * Available only for the library internals to grab the + * response instance provided by the developer. + * @note This promise cannot be rejected. It's either infinitely + * pending or resolved with whichever Response was passed to `respondWith()`. + */ + [kResponsePromise]: DeferredPromise; + /** + * Internal flag indicating if this request has been handled. + * @note The response promise becomes "fulfilled" on the next tick. + */ + [kRequestHandled]: boolean; + constructor(request: Request); + /** + * Respond to this request with the given `Response` instance. + * @example + * controller.respondWith(new Response()) + * controller.respondWith(Response.json({ id })) + * controller.respondWith(Response.error()) + */ + respondWith(response: Response): void; + /** + * Error this request with the given error. + * @example + * controller.errorWith() + * controller.errorWith(new Error('Oops!')) + */ + errorWith(error?: Error): void; +} + +declare const IS_PATCHED_MODULE: unique symbol; + +type RequestCredentials = 'omit' | 'include' | 'same-origin'; +type HttpRequestEventMap = { + request: [ + args: { + request: Request; + requestId: string; + controller: RequestController; + } + ]; + response: [ + args: { + response: Response; + isMockedResponse: boolean; + request: Request; + requestId: string; + } + ]; + unhandledException: [ + args: { + error: unknown; + request: Request; + requestId: string; + controller: RequestController; + } + ]; +}; + +type InterceptorEventMap = Record; +type InterceptorSubscription = () => void; +/** + * Request header name to detect when a single request + * is being handled by nested interceptors (XHR -> ClientRequest). + * Obscure by design to prevent collisions with user-defined headers. + * Ideally, come up with the Interceptor-level mechanism for this. + * @see https://github.com/mswjs/interceptors/issues/378 + */ +declare const INTERNAL_REQUEST_ID_HEADER_NAME = "x-interceptors-internal-request-id"; +declare function getGlobalSymbol(symbol: Symbol): V | undefined; +declare function deleteGlobalSymbol(symbol: Symbol): void; +declare enum InterceptorReadyState { + INACTIVE = "INACTIVE", + APPLYING = "APPLYING", + APPLIED = "APPLIED", + DISPOSING = "DISPOSING", + DISPOSED = "DISPOSED" +} +type ExtractEventNames> = Events extends Record ? EventName : never; +declare class Interceptor { + private readonly symbol; + protected emitter: Emitter; + protected subscriptions: Array; + protected logger: Logger; + readyState: InterceptorReadyState; + constructor(symbol: symbol); + /** + * Determine if this interceptor can be applied + * in the current environment. + */ + protected checkEnvironment(): boolean; + /** + * Apply this interceptor to the current process. + * Returns an already running interceptor instance if it's present. + */ + apply(): void; + /** + * Setup the module augments and stubs necessary for this interceptor. + * This method is not run if there's a running interceptor instance + * to prevent instantiating an interceptor multiple times. + */ + protected setup(): void; + /** + * Listen to the interceptor's public events. + */ + on>(event: EventName, listener: Listener): this; + once>(event: EventName, listener: Listener): this; + off>(event: EventName, listener: Listener): this; + removeAllListeners>(event?: EventName): this; + /** + * Disposes of any side-effects this interceptor has introduced. + */ + dispose(): void; + private getInstance; + private setInstance; + private clearInstance; +} + +export { ExtractEventNames as E, HttpRequestEventMap as H, IS_PATCHED_MODULE as I, RequestController as R, RequestCredentials as a, InterceptorEventMap as b, InterceptorSubscription as c, INTERNAL_REQUEST_ID_HEADER_NAME as d, deleteGlobalSymbol as e, InterceptorReadyState as f, getGlobalSymbol as g, Interceptor as h }; diff --git a/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.d.ts b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.d.ts new file mode 100644 index 0000000000..67c0866cad --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.d.ts @@ -0,0 +1,43 @@ +import { ChildProcess } from 'child_process'; +import { h as Interceptor, H as HttpRequestEventMap } from './Interceptor-436630be.js'; +import { a as BatchInterceptor } from './BatchInterceptor-67bf41ba.js'; +import { ClientRequestInterceptor } from './interceptors/ClientRequest/index.js'; +import { XMLHttpRequestInterceptor } from './interceptors/XMLHttpRequest/index.js'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; +import 'strict-event-emitter'; +import 'node:net'; + +interface SerializedRequest { + id: string; + url: string; + method: string; + headers: Array<[string, string]>; + credentials: RequestCredentials; + body: string; +} +interface SerializedResponse { + status: number; + statusText: string; + headers: Array<[string, string]>; + body: string; +} +declare class RemoteHttpInterceptor extends BatchInterceptor<[ + ClientRequestInterceptor, + XMLHttpRequestInterceptor +]> { + constructor(); + protected setup(): void; +} +declare function requestReviver(key: string, value: any): any; +interface RemoveResolverOptions { + process: ChildProcess; +} +declare class RemoteHttpResolver extends Interceptor { + static symbol: symbol; + private process; + constructor(options: RemoveResolverOptions); + protected setup(): void; +} + +export { RemoteHttpInterceptor, RemoteHttpResolver, RemoveResolverOptions, SerializedRequest, SerializedResponse, requestReviver }; diff --git a/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.js b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.js new file mode 100644 index 0000000000..266357ab9c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.js @@ -0,0 +1,187 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkYBN5MFAPjs = require('./chunk-YBN5MFAP.js'); + + +var _chunk4IGRW7SKjs = require('./chunk-4IGRW7SK.js'); + + +var _chunkLCA4FKWYjs = require('./chunk-LCA4FKWY.js'); +require('./chunk-LK6DILFK.js'); +require('./chunk-PFGO5BSM.js'); +require('./chunk-73NOP3T5.js'); + + + +var _chunk6L3PFBGTjs = require('./chunk-6L3PFBGT.js'); + + + +var _chunkWZTE4PCOjs = require('./chunk-WZTE4PCO.js'); + +// src/RemoteHttpInterceptor.ts +var RemoteHttpInterceptor = class extends _chunkYBN5MFAPjs.BatchInterceptor { + constructor() { + super({ + name: "remote-interceptor", + interceptors: [ + new (0, _chunk4IGRW7SKjs.ClientRequestInterceptor)(), + new (0, _chunkLCA4FKWYjs.XMLHttpRequestInterceptor)() + ] + }); + } + setup() { + super.setup(); + let handleParentMessage; + this.on("request", async ({ request, requestId, controller }) => { + var _a; + const serializedRequest = JSON.stringify({ + id: requestId, + method: request.method, + url: request.url, + headers: Array.from(request.headers.entries()), + credentials: request.credentials, + body: ["GET", "HEAD"].includes(request.method) ? null : await request.text() + }); + this.logger.info( + "sent serialized request to the child:", + serializedRequest + ); + (_a = process.send) == null ? void 0 : _a.call(process, `request:${serializedRequest}`); + const responsePromise = new Promise((resolve) => { + handleParentMessage = (message) => { + if (typeof message !== "string") { + return resolve(); + } + if (message.startsWith(`response:${requestId}`)) { + const [, serializedResponse] = message.match(/^response:.+?:(.+)$/) || []; + if (!serializedResponse) { + return resolve(); + } + const responseInit = JSON.parse( + serializedResponse + ); + const mockedResponse = new (0, _chunkWZTE4PCOjs.FetchResponse)(responseInit.body, { + url: request.url, + status: responseInit.status, + statusText: responseInit.statusText, + headers: responseInit.headers + }); + controller.respondWith(mockedResponse); + return resolve(); + } + }; + }); + this.logger.info( + 'add "message" listener to the parent process', + handleParentMessage + ); + process.addListener("message", handleParentMessage); + return responsePromise; + }); + this.subscriptions.push(() => { + process.removeListener("message", handleParentMessage); + }); + } +}; +function requestReviver(key, value) { + switch (key) { + case "url": + return new URL(value); + case "headers": + return new Headers(value); + default: + return value; + } +} +var _RemoteHttpResolver = class extends _chunkWZTE4PCOjs.Interceptor { + constructor(options) { + super(_RemoteHttpResolver.symbol); + this.process = options.process; + } + setup() { + const logger = this.logger.extend("setup"); + const handleChildMessage = async (message) => { + logger.info("received message from child!", message); + if (typeof message !== "string" || !message.startsWith("request:")) { + logger.info("unknown message, ignoring..."); + return; + } + const [, serializedRequest] = message.match(/^request:(.+)$/) || []; + if (!serializedRequest) { + return; + } + const requestJson = JSON.parse( + serializedRequest, + requestReviver + ); + logger.info("parsed intercepted request", requestJson); + const request = new Request(requestJson.url, { + method: requestJson.method, + headers: new Headers(requestJson.headers), + credentials: requestJson.credentials, + body: requestJson.body + }); + const controller = new (0, _chunk6L3PFBGTjs.RequestController)(request); + await _chunk6L3PFBGTjs.handleRequest.call(void 0, { + request, + requestId: requestJson.id, + controller, + emitter: this.emitter, + onResponse: async (response) => { + this.logger.info("received mocked response!", { response }); + const responseClone = response.clone(); + const responseText = await responseClone.text(); + const serializedResponse = JSON.stringify({ + status: response.status, + statusText: response.statusText, + headers: Array.from(response.headers.entries()), + body: responseText + }); + this.process.send( + `response:${requestJson.id}:${serializedResponse}`, + (error) => { + if (error) { + return; + } + this.emitter.emit("response", { + request, + requestId: requestJson.id, + response: responseClone, + isMockedResponse: true + }); + } + ); + logger.info( + "sent serialized mocked response to the parent:", + serializedResponse + ); + }, + onRequestError: (response) => { + this.logger.info("received a network error!", { response }); + throw new Error("Not implemented"); + }, + onError: (error) => { + this.logger.info("request has errored!", { error }); + throw new Error("Not implemented"); + } + }); + }; + this.subscriptions.push(() => { + this.process.removeListener("message", handleChildMessage); + logger.info('removed the "message" listener from the child process!'); + }); + logger.info('adding a "message" listener to the child process'); + this.process.addListener("message", handleChildMessage); + this.process.once("error", () => this.dispose()); + this.process.once("exit", () => this.dispose()); + } +}; +var RemoteHttpResolver = _RemoteHttpResolver; +RemoteHttpResolver.symbol = Symbol("remote-resolver"); + + + + +exports.RemoteHttpInterceptor = RemoteHttpInterceptor; exports.RemoteHttpResolver = RemoteHttpResolver; exports.requestReviver = requestReviver; +//# sourceMappingURL=RemoteHttpInterceptor.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.js.map b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.js.map new file mode 100644 index 0000000000..f44fcd3058 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/RemoteHttpInterceptor.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChildProcess } from 'child_process'\nimport { HttpRequestEventMap } from './glossary'\nimport { Interceptor } from './Interceptor'\nimport { BatchInterceptor } from './BatchInterceptor'\nimport { ClientRequestInterceptor } from './interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from './interceptors/XMLHttpRequest'\nimport { handleRequest } from './utils/handleRequest'\nimport { RequestController } from './RequestController'\nimport { FetchResponse } from './utils/fetchUtils'\n\nexport interface SerializedRequest {\n id: string\n url: string\n method: string\n headers: Array<[string, string]>\n credentials: RequestCredentials\n body: string\n}\n\ninterface RevivedRequest extends Omit {\n url: URL\n headers: Headers\n}\n\nexport interface SerializedResponse {\n status: number\n statusText: string\n headers: Array<[string, string]>\n body: string\n}\n\nexport class RemoteHttpInterceptor extends BatchInterceptor<\n [ClientRequestInterceptor, XMLHttpRequestInterceptor]\n> {\n constructor() {\n super({\n name: 'remote-interceptor',\n interceptors: [\n new ClientRequestInterceptor(),\n new XMLHttpRequestInterceptor(),\n ],\n })\n }\n\n protected setup() {\n super.setup()\n\n let handleParentMessage: NodeJS.MessageListener\n\n this.on('request', async ({ request, requestId, controller }) => {\n // Send the stringified intercepted request to\n // the parent process where the remote resolver is established.\n const serializedRequest = JSON.stringify({\n id: requestId,\n method: request.method,\n url: request.url,\n headers: Array.from(request.headers.entries()),\n credentials: request.credentials,\n body: ['GET', 'HEAD'].includes(request.method)\n ? null\n : await request.text(),\n } as SerializedRequest)\n\n this.logger.info(\n 'sent serialized request to the child:',\n serializedRequest\n )\n\n process.send?.(`request:${serializedRequest}`)\n\n const responsePromise = new Promise((resolve) => {\n handleParentMessage = (message) => {\n if (typeof message !== 'string') {\n return resolve()\n }\n\n if (message.startsWith(`response:${requestId}`)) {\n const [, serializedResponse] =\n message.match(/^response:.+?:(.+)$/) || []\n\n if (!serializedResponse) {\n return resolve()\n }\n\n const responseInit = JSON.parse(\n serializedResponse\n ) as SerializedResponse\n\n const mockedResponse = new FetchResponse(responseInit.body, {\n url: request.url,\n status: responseInit.status,\n statusText: responseInit.statusText,\n headers: responseInit.headers,\n })\n\n /**\n * @todo Support \"errorWith\" as well.\n * This response handling from the child is incomplete.\n */\n\n controller.respondWith(mockedResponse)\n return resolve()\n }\n }\n })\n\n // Listen for the mocked response message from the parent.\n this.logger.info(\n 'add \"message\" listener to the parent process',\n handleParentMessage\n )\n process.addListener('message', handleParentMessage)\n\n return responsePromise\n })\n\n this.subscriptions.push(() => {\n process.removeListener('message', handleParentMessage)\n })\n }\n}\n\nexport function requestReviver(key: string, value: any) {\n switch (key) {\n case 'url':\n return new URL(value)\n\n case 'headers':\n return new Headers(value)\n\n default:\n return value\n }\n}\n\nexport interface RemoveResolverOptions {\n process: ChildProcess\n}\n\nexport class RemoteHttpResolver extends Interceptor {\n static symbol = Symbol('remote-resolver')\n private process: ChildProcess\n\n constructor(options: RemoveResolverOptions) {\n super(RemoteHttpResolver.symbol)\n this.process = options.process\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n const handleChildMessage: NodeJS.MessageListener = async (message) => {\n logger.info('received message from child!', message)\n\n if (typeof message !== 'string' || !message.startsWith('request:')) {\n logger.info('unknown message, ignoring...')\n return\n }\n\n const [, serializedRequest] = message.match(/^request:(.+)$/) || []\n if (!serializedRequest) {\n return\n }\n\n const requestJson = JSON.parse(\n serializedRequest,\n requestReviver\n ) as RevivedRequest\n\n logger.info('parsed intercepted request', requestJson)\n\n const request = new Request(requestJson.url, {\n method: requestJson.method,\n headers: new Headers(requestJson.headers),\n credentials: requestJson.credentials,\n body: requestJson.body,\n })\n\n const controller = new RequestController(request)\n await handleRequest({\n request,\n requestId: requestJson.id,\n controller,\n emitter: this.emitter,\n onResponse: async (response) => {\n this.logger.info('received mocked response!', { response })\n\n const responseClone = response.clone()\n const responseText = await responseClone.text()\n\n // // Send the mocked response to the child process.\n const serializedResponse = JSON.stringify({\n status: response.status,\n statusText: response.statusText,\n headers: Array.from(response.headers.entries()),\n body: responseText,\n } as SerializedResponse)\n\n this.process.send(\n `response:${requestJson.id}:${serializedResponse}`,\n (error) => {\n if (error) {\n return\n }\n\n // Emit an optimistic \"response\" event at this point,\n // not to rely on the back-and-forth signaling for the sake of the event.\n this.emitter.emit('response', {\n request,\n requestId: requestJson.id,\n response: responseClone,\n isMockedResponse: true,\n })\n }\n )\n\n logger.info(\n 'sent serialized mocked response to the parent:',\n serializedResponse\n )\n },\n onRequestError: (response) => {\n this.logger.info('received a network error!', { response })\n throw new Error('Not implemented')\n },\n onError: (error) => {\n this.logger.info('request has errored!', { error })\n throw new Error('Not implemented')\n },\n })\n }\n\n this.subscriptions.push(() => {\n this.process.removeListener('message', handleChildMessage)\n logger.info('removed the \"message\" listener from the child process!')\n })\n\n logger.info('adding a \"message\" listener to the child process')\n this.process.addListener('message', handleChildMessage)\n\n this.process.once('error', () => this.dispose())\n this.process.once('exit', () => this.dispose())\n }\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.mjs b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.mjs new file mode 100644 index 0000000000..9ffd41a1e2 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.mjs @@ -0,0 +1,187 @@ +import { + BatchInterceptor +} from "./chunk-PJA4E426.mjs"; +import { + ClientRequestInterceptor +} from "./chunk-QFFDMWKW.mjs"; +import { + XMLHttpRequestInterceptor +} from "./chunk-OMWE7UVM.mjs"; +import "./chunk-6HYIRFX2.mjs"; +import "./chunk-TX5GBTFY.mjs"; +import "./chunk-6YM4PLBI.mjs"; +import { + RequestController, + handleRequest +} from "./chunk-5KMS5CTP.mjs"; +import { + FetchResponse, + Interceptor +} from "./chunk-I7HQIBT7.mjs"; + +// src/RemoteHttpInterceptor.ts +var RemoteHttpInterceptor = class extends BatchInterceptor { + constructor() { + super({ + name: "remote-interceptor", + interceptors: [ + new ClientRequestInterceptor(), + new XMLHttpRequestInterceptor() + ] + }); + } + setup() { + super.setup(); + let handleParentMessage; + this.on("request", async ({ request, requestId, controller }) => { + var _a; + const serializedRequest = JSON.stringify({ + id: requestId, + method: request.method, + url: request.url, + headers: Array.from(request.headers.entries()), + credentials: request.credentials, + body: ["GET", "HEAD"].includes(request.method) ? null : await request.text() + }); + this.logger.info( + "sent serialized request to the child:", + serializedRequest + ); + (_a = process.send) == null ? void 0 : _a.call(process, `request:${serializedRequest}`); + const responsePromise = new Promise((resolve) => { + handleParentMessage = (message) => { + if (typeof message !== "string") { + return resolve(); + } + if (message.startsWith(`response:${requestId}`)) { + const [, serializedResponse] = message.match(/^response:.+?:(.+)$/) || []; + if (!serializedResponse) { + return resolve(); + } + const responseInit = JSON.parse( + serializedResponse + ); + const mockedResponse = new FetchResponse(responseInit.body, { + url: request.url, + status: responseInit.status, + statusText: responseInit.statusText, + headers: responseInit.headers + }); + controller.respondWith(mockedResponse); + return resolve(); + } + }; + }); + this.logger.info( + 'add "message" listener to the parent process', + handleParentMessage + ); + process.addListener("message", handleParentMessage); + return responsePromise; + }); + this.subscriptions.push(() => { + process.removeListener("message", handleParentMessage); + }); + } +}; +function requestReviver(key, value) { + switch (key) { + case "url": + return new URL(value); + case "headers": + return new Headers(value); + default: + return value; + } +} +var _RemoteHttpResolver = class extends Interceptor { + constructor(options) { + super(_RemoteHttpResolver.symbol); + this.process = options.process; + } + setup() { + const logger = this.logger.extend("setup"); + const handleChildMessage = async (message) => { + logger.info("received message from child!", message); + if (typeof message !== "string" || !message.startsWith("request:")) { + logger.info("unknown message, ignoring..."); + return; + } + const [, serializedRequest] = message.match(/^request:(.+)$/) || []; + if (!serializedRequest) { + return; + } + const requestJson = JSON.parse( + serializedRequest, + requestReviver + ); + logger.info("parsed intercepted request", requestJson); + const request = new Request(requestJson.url, { + method: requestJson.method, + headers: new Headers(requestJson.headers), + credentials: requestJson.credentials, + body: requestJson.body + }); + const controller = new RequestController(request); + await handleRequest({ + request, + requestId: requestJson.id, + controller, + emitter: this.emitter, + onResponse: async (response) => { + this.logger.info("received mocked response!", { response }); + const responseClone = response.clone(); + const responseText = await responseClone.text(); + const serializedResponse = JSON.stringify({ + status: response.status, + statusText: response.statusText, + headers: Array.from(response.headers.entries()), + body: responseText + }); + this.process.send( + `response:${requestJson.id}:${serializedResponse}`, + (error) => { + if (error) { + return; + } + this.emitter.emit("response", { + request, + requestId: requestJson.id, + response: responseClone, + isMockedResponse: true + }); + } + ); + logger.info( + "sent serialized mocked response to the parent:", + serializedResponse + ); + }, + onRequestError: (response) => { + this.logger.info("received a network error!", { response }); + throw new Error("Not implemented"); + }, + onError: (error) => { + this.logger.info("request has errored!", { error }); + throw new Error("Not implemented"); + } + }); + }; + this.subscriptions.push(() => { + this.process.removeListener("message", handleChildMessage); + logger.info('removed the "message" listener from the child process!'); + }); + logger.info('adding a "message" listener to the child process'); + this.process.addListener("message", handleChildMessage); + this.process.once("error", () => this.dispose()); + this.process.once("exit", () => this.dispose()); + } +}; +var RemoteHttpResolver = _RemoteHttpResolver; +RemoteHttpResolver.symbol = Symbol("remote-resolver"); +export { + RemoteHttpInterceptor, + RemoteHttpResolver, + requestReviver +}; +//# sourceMappingURL=RemoteHttpInterceptor.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.mjs.map b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.mjs.map new file mode 100644 index 0000000000..b8ef19807a --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/RemoteHttpInterceptor.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/RemoteHttpInterceptor.ts"],"sourcesContent":["import { ChildProcess } from 'child_process'\nimport { HttpRequestEventMap } from './glossary'\nimport { Interceptor } from './Interceptor'\nimport { BatchInterceptor } from './BatchInterceptor'\nimport { ClientRequestInterceptor } from './interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from './interceptors/XMLHttpRequest'\nimport { handleRequest } from './utils/handleRequest'\nimport { RequestController } from './RequestController'\nimport { FetchResponse } from './utils/fetchUtils'\n\nexport interface SerializedRequest {\n id: string\n url: string\n method: string\n headers: Array<[string, string]>\n credentials: RequestCredentials\n body: string\n}\n\ninterface RevivedRequest extends Omit {\n url: URL\n headers: Headers\n}\n\nexport interface SerializedResponse {\n status: number\n statusText: string\n headers: Array<[string, string]>\n body: string\n}\n\nexport class RemoteHttpInterceptor extends BatchInterceptor<\n [ClientRequestInterceptor, XMLHttpRequestInterceptor]\n> {\n constructor() {\n super({\n name: 'remote-interceptor',\n interceptors: [\n new ClientRequestInterceptor(),\n new XMLHttpRequestInterceptor(),\n ],\n })\n }\n\n protected setup() {\n super.setup()\n\n let handleParentMessage: NodeJS.MessageListener\n\n this.on('request', async ({ request, requestId, controller }) => {\n // Send the stringified intercepted request to\n // the parent process where the remote resolver is established.\n const serializedRequest = JSON.stringify({\n id: requestId,\n method: request.method,\n url: request.url,\n headers: Array.from(request.headers.entries()),\n credentials: request.credentials,\n body: ['GET', 'HEAD'].includes(request.method)\n ? null\n : await request.text(),\n } as SerializedRequest)\n\n this.logger.info(\n 'sent serialized request to the child:',\n serializedRequest\n )\n\n process.send?.(`request:${serializedRequest}`)\n\n const responsePromise = new Promise((resolve) => {\n handleParentMessage = (message) => {\n if (typeof message !== 'string') {\n return resolve()\n }\n\n if (message.startsWith(`response:${requestId}`)) {\n const [, serializedResponse] =\n message.match(/^response:.+?:(.+)$/) || []\n\n if (!serializedResponse) {\n return resolve()\n }\n\n const responseInit = JSON.parse(\n serializedResponse\n ) as SerializedResponse\n\n const mockedResponse = new FetchResponse(responseInit.body, {\n url: request.url,\n status: responseInit.status,\n statusText: responseInit.statusText,\n headers: responseInit.headers,\n })\n\n /**\n * @todo Support \"errorWith\" as well.\n * This response handling from the child is incomplete.\n */\n\n controller.respondWith(mockedResponse)\n return resolve()\n }\n }\n })\n\n // Listen for the mocked response message from the parent.\n this.logger.info(\n 'add \"message\" listener to the parent process',\n handleParentMessage\n )\n process.addListener('message', handleParentMessage)\n\n return responsePromise\n })\n\n this.subscriptions.push(() => {\n process.removeListener('message', handleParentMessage)\n })\n }\n}\n\nexport function requestReviver(key: string, value: any) {\n switch (key) {\n case 'url':\n return new URL(value)\n\n case 'headers':\n return new Headers(value)\n\n default:\n return value\n }\n}\n\nexport interface RemoveResolverOptions {\n process: ChildProcess\n}\n\nexport class RemoteHttpResolver extends Interceptor {\n static symbol = Symbol('remote-resolver')\n private process: ChildProcess\n\n constructor(options: RemoveResolverOptions) {\n super(RemoteHttpResolver.symbol)\n this.process = options.process\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n const handleChildMessage: NodeJS.MessageListener = async (message) => {\n logger.info('received message from child!', message)\n\n if (typeof message !== 'string' || !message.startsWith('request:')) {\n logger.info('unknown message, ignoring...')\n return\n }\n\n const [, serializedRequest] = message.match(/^request:(.+)$/) || []\n if (!serializedRequest) {\n return\n }\n\n const requestJson = JSON.parse(\n serializedRequest,\n requestReviver\n ) as RevivedRequest\n\n logger.info('parsed intercepted request', requestJson)\n\n const request = new Request(requestJson.url, {\n method: requestJson.method,\n headers: new Headers(requestJson.headers),\n credentials: requestJson.credentials,\n body: requestJson.body,\n })\n\n const controller = new RequestController(request)\n await handleRequest({\n request,\n requestId: requestJson.id,\n controller,\n emitter: this.emitter,\n onResponse: async (response) => {\n this.logger.info('received mocked response!', { response })\n\n const responseClone = response.clone()\n const responseText = await responseClone.text()\n\n // // Send the mocked response to the child process.\n const serializedResponse = JSON.stringify({\n status: response.status,\n statusText: response.statusText,\n headers: Array.from(response.headers.entries()),\n body: responseText,\n } as SerializedResponse)\n\n this.process.send(\n `response:${requestJson.id}:${serializedResponse}`,\n (error) => {\n if (error) {\n return\n }\n\n // Emit an optimistic \"response\" event at this point,\n // not to rely on the back-and-forth signaling for the sake of the event.\n this.emitter.emit('response', {\n request,\n requestId: requestJson.id,\n response: responseClone,\n isMockedResponse: true,\n })\n }\n )\n\n logger.info(\n 'sent serialized mocked response to the parent:',\n serializedResponse\n )\n },\n onRequestError: (response) => {\n this.logger.info('received a network error!', { response })\n throw new Error('Not implemented')\n },\n onError: (error) => {\n this.logger.info('request has errored!', { error })\n throw new Error('Not implemented')\n },\n })\n }\n\n this.subscriptions.push(() => {\n this.process.removeListener('message', handleChildMessage)\n logger.info('removed the \"message\" listener from the child process!')\n })\n\n logger.info('adding a \"message\" listener to the child process')\n this.process.addListener('message', handleChildMessage)\n\n this.process.once('error', () => this.dispose())\n this.process.once('exit', () => this.dispose())\n }\n}\n"],"mappings":"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","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-4IGRW7SK.js b/node_modules/@mswjs/interceptors/lib/node/chunk-4IGRW7SK.js new file mode 100644 index 0000000000..f830840e8e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-4IGRW7SK.js @@ -0,0 +1,1053 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + + + + +var _chunk6L3PFBGTjs = require('./chunk-6L3PFBGT.js'); + + + + + +var _chunkWZTE4PCOjs = require('./chunk-WZTE4PCO.js'); + +// src/interceptors/ClientRequest/index.ts +var _http = require('http'); var _http2 = _interopRequireDefault(_http); +var _https = require('https'); var _https2 = _interopRequireDefault(_https); + +// src/interceptors/ClientRequest/MockHttpSocket.ts +var _net = require('net'); var _net2 = _interopRequireDefault(_net); + + +var __http_common = require('_http_common'); + +var _stream = require('stream'); +var _outvariant = require('outvariant'); + +// src/interceptors/Socket/MockSocket.ts + + +// src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +function normalizeSocketWriteArgs(args) { + const normalized = [args[0], void 0, void 0]; + if (typeof args[1] === "string") { + normalized[1] = args[1]; + } else if (typeof args[1] === "function") { + normalized[2] = args[1]; + } + if (typeof args[2] === "function") { + normalized[2] = args[2]; + } + return normalized; +} + +// src/interceptors/Socket/MockSocket.ts +var MockSocket = class extends _net2.default.Socket { + constructor(options) { + super(); + this.options = options; + this.connecting = false; + this.connect(); + this._final = (callback) => { + callback(null); + }; + } + connect() { + this.connecting = true; + return this; + } + write(...args) { + const [chunk, encoding, callback] = normalizeSocketWriteArgs( + args + ); + this.options.write(chunk, encoding, callback); + return true; + } + end(...args) { + const [chunk, encoding, callback] = normalizeSocketWriteArgs( + args + ); + this.options.write(chunk, encoding, callback); + return super.end.apply(this, args); + } + push(chunk, encoding) { + this.options.read(chunk, encoding); + return super.push(chunk, encoding); + } +}; + +// src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +function baseUrlFromConnectionOptions(options) { + if ("href" in options) { + return new URL(options.href); + } + const protocol = options.port === 443 ? "https:" : "http:"; + const host = options.host; + const url = new URL(`${protocol}//${host}`); + if (options.port) { + url.port = options.port.toString(); + } + if (options.path) { + url.pathname = options.path; + } + if (options.auth) { + const [username, password] = options.auth.split(":"); + url.username = username; + url.password = password; + } + return url; +} + +// src/interceptors/ClientRequest/utils/recordRawHeaders.ts +var kRawHeaders = Symbol("kRawHeaders"); +var kRestorePatches = Symbol("kRestorePatches"); +function recordRawHeader(headers, args, behavior) { + ensureRawHeadersSymbol(headers, []); + const rawHeaders = Reflect.get(headers, kRawHeaders); + if (behavior === "set") { + for (let index = rawHeaders.length - 1; index >= 0; index--) { + if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) { + rawHeaders.splice(index, 1); + } + } + } + rawHeaders.push(args); +} +function ensureRawHeadersSymbol(headers, rawHeaders) { + if (Reflect.has(headers, kRawHeaders)) { + return; + } + defineRawHeadersSymbol(headers, rawHeaders); +} +function defineRawHeadersSymbol(headers, rawHeaders) { + Object.defineProperty(headers, kRawHeaders, { + value: rawHeaders, + enumerable: false, + // Mark the symbol as configurable so its value can be overridden. + // Overrides happen when merging raw headers from multiple sources. + // E.g. new Request(new Request(url, { headers }), { headers }) + configurable: true + }); +} +function recordRawFetchHeaders() { + if (Reflect.get(Headers, kRestorePatches)) { + return Reflect.get(Headers, kRestorePatches); + } + const { + Headers: OriginalHeaders, + Request: OriginalRequest, + Response: OriginalResponse + } = globalThis; + const { set, append, delete: headersDeleteMethod } = Headers.prototype; + Object.defineProperty(Headers, kRestorePatches, { + value: () => { + Headers.prototype.set = set; + Headers.prototype.append = append; + Headers.prototype.delete = headersDeleteMethod; + globalThis.Headers = OriginalHeaders; + globalThis.Request = OriginalRequest; + globalThis.Response = OriginalResponse; + Reflect.deleteProperty(Headers, kRestorePatches); + }, + enumerable: false, + /** + * @note Mark this property as configurable + * so we can delete it using `Reflect.delete` during cleanup. + */ + configurable: true + }); + Object.defineProperty(globalThis, "Headers", { + enumerable: true, + writable: true, + value: new Proxy(Headers, { + construct(target, args, newTarget) { + const headersInit = args[0] || []; + if (headersInit instanceof Headers && Reflect.has(headersInit, kRawHeaders)) { + const headers2 = Reflect.construct( + target, + [Reflect.get(headersInit, kRawHeaders)], + newTarget + ); + ensureRawHeadersSymbol(headers2, [ + /** + * @note Spread the retrieved headers to clone them. + * This prevents multiple Headers instances from pointing + * at the same internal "rawHeaders" array. + */ + ...Reflect.get(headersInit, kRawHeaders) + ]); + return headers2; + } + const headers = Reflect.construct(target, args, newTarget); + if (!Reflect.has(headers, kRawHeaders)) { + const rawHeadersInit = Array.isArray(headersInit) ? headersInit : Object.entries(headersInit); + ensureRawHeadersSymbol(headers, rawHeadersInit); + } + return headers; + } + }) + }); + Headers.prototype.set = new Proxy(Headers.prototype.set, { + apply(target, thisArg, args) { + recordRawHeader(thisArg, args, "set"); + return Reflect.apply(target, thisArg, args); + } + }); + Headers.prototype.append = new Proxy(Headers.prototype.append, { + apply(target, thisArg, args) { + recordRawHeader(thisArg, args, "append"); + return Reflect.apply(target, thisArg, args); + } + }); + Headers.prototype.delete = new Proxy(Headers.prototype.delete, { + apply(target, thisArg, args) { + const rawHeaders = Reflect.get(thisArg, kRawHeaders); + if (rawHeaders) { + for (let index = rawHeaders.length - 1; index >= 0; index--) { + if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) { + rawHeaders.splice(index, 1); + } + } + } + return Reflect.apply(target, thisArg, args); + } + }); + Object.defineProperty(globalThis, "Request", { + enumerable: true, + writable: true, + value: new Proxy(Request, { + construct(target, args, newTarget) { + const request = Reflect.construct(target, args, newTarget); + const inferredRawHeaders = []; + if (typeof args[0] === "object" && args[0].headers != null) { + inferredRawHeaders.push(...inferRawHeaders(args[0].headers)); + } + if (typeof args[1] === "object" && args[1].headers != null) { + inferredRawHeaders.push(...inferRawHeaders(args[1].headers)); + } + if (inferredRawHeaders.length > 0) { + ensureRawHeadersSymbol(request.headers, inferredRawHeaders); + } + return request; + } + }) + }); + Object.defineProperty(globalThis, "Response", { + enumerable: true, + writable: true, + value: new Proxy(Response, { + construct(target, args, newTarget) { + const response = Reflect.construct(target, args, newTarget); + if (typeof args[1] === "object" && args[1].headers != null) { + ensureRawHeadersSymbol( + response.headers, + inferRawHeaders(args[1].headers) + ); + } + return response; + } + }) + }); +} +function restoreHeadersPrototype() { + if (!Reflect.get(Headers, kRestorePatches)) { + return; + } + Reflect.get(Headers, kRestorePatches)(); +} +function getRawFetchHeaders(headers) { + if (!Reflect.has(headers, kRawHeaders)) { + return Array.from(headers.entries()); + } + const rawHeaders = Reflect.get(headers, kRawHeaders); + return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries()); +} +function inferRawHeaders(headers) { + if (headers instanceof Headers) { + return Reflect.get(headers, kRawHeaders) || []; + } + return Reflect.get(new Headers(headers), kRawHeaders); +} + +// src/interceptors/ClientRequest/MockHttpSocket.ts +var kRequestId = Symbol("kRequestId"); +var MockHttpSocket = class extends MockSocket { + constructor(options) { + super({ + write: (chunk, encoding, callback) => { + var _a; + if (this.socketState !== "passthrough") { + this.writeBuffer.push([chunk, encoding, callback]); + } + if (chunk) { + if (this.socketState === "passthrough") { + (_a = this.originalSocket) == null ? void 0 : _a.write(chunk, encoding, callback); + } + this.requestParser.execute( + Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding) + ); + } + }, + read: (chunk) => { + if (chunk !== null) { + this.responseParser.execute( + Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk) + ); + } + } + }); + this.writeBuffer = []; + this.socketState = "unknown"; + this.onRequestStart = (versionMajor, versionMinor, rawHeaders, _, path, __, ___, ____, shouldKeepAlive) => { + var _a; + this.shouldKeepAlive = shouldKeepAlive; + const url = new URL(path, this.baseUrl); + const method = ((_a = this.connectionOptions.method) == null ? void 0 : _a.toUpperCase()) || "GET"; + const headers = _chunkWZTE4PCOjs.FetchResponse.parseRawHeaders(rawHeaders); + const canHaveBody = method !== "GET" && method !== "HEAD"; + if (url.username || url.password) { + if (!headers.has("authorization")) { + headers.set("authorization", `Basic ${url.username}:${url.password}`); + } + url.username = ""; + url.password = ""; + } + if (canHaveBody) { + this.requestStream = new (0, _stream.Readable)({ + /** + * @note Provide the `read()` method so a `Readable` could be + * used as the actual request body (the stream calls "read()"). + * We control the queue in the onRequestBody/End functions. + */ + read: () => { + this.flushWriteBuffer(); + } + }); + } + const requestId = _chunkWZTE4PCOjs.createRequestId.call(void 0, ); + this.request = new Request(url, { + method, + headers, + credentials: "same-origin", + // @ts-expect-error Undocumented Fetch property. + duplex: canHaveBody ? "half" : void 0, + body: canHaveBody ? _stream.Readable.toWeb(this.requestStream) : null + }); + Reflect.set(this.request, kRequestId, requestId); + if (this.request.headers.has(_chunkWZTE4PCOjs.INTERNAL_REQUEST_ID_HEADER_NAME)) { + this.passthrough(); + return; + } + this.onRequest({ + requestId, + request: this.request, + socket: this + }); + }; + this.onResponseStart = (versionMajor, versionMinor, rawHeaders, method, url, status, statusText) => { + const headers = _chunkWZTE4PCOjs.FetchResponse.parseRawHeaders(rawHeaders); + const response = new (0, _chunkWZTE4PCOjs.FetchResponse)( + /** + * @note The Fetch API response instance exposed to the consumer + * is created over the response stream of the HTTP parser. It is NOT + * related to the Socket instance. This way, you can read response body + * in response listener while the Socket instance delays the emission + * of "end" and other events until those response listeners are finished. + */ + _chunkWZTE4PCOjs.FetchResponse.isResponseWithBody(status) ? _stream.Readable.toWeb( + this.responseStream = new (0, _stream.Readable)({ read() { + } }) + ) : null, + { + url, + status, + statusText, + headers + } + ); + _outvariant.invariant.call(void 0, + this.request, + "Failed to handle a response: request does not exist" + ); + if (this.request.headers.has(_chunkWZTE4PCOjs.INTERNAL_REQUEST_ID_HEADER_NAME)) { + return; + } + this.responseListenersPromise = this.onResponse({ + response, + isMockedResponse: this.socketState === "mock", + requestId: Reflect.get(this.request, kRequestId), + request: this.request, + socket: this + }); + }; + this.connectionOptions = options.connectionOptions; + this.createConnection = options.createConnection; + this.onRequest = options.onRequest; + this.onResponse = options.onResponse; + this.baseUrl = baseUrlFromConnectionOptions(this.connectionOptions); + this.requestParser = new (0, __http_common.HTTPParser)(); + this.requestParser.initialize(__http_common.HTTPParser.REQUEST, {}); + this.requestParser[__http_common.HTTPParser.kOnHeadersComplete] = this.onRequestStart.bind(this); + this.requestParser[__http_common.HTTPParser.kOnBody] = this.onRequestBody.bind(this); + this.requestParser[__http_common.HTTPParser.kOnMessageComplete] = this.onRequestEnd.bind(this); + this.responseParser = new (0, __http_common.HTTPParser)(); + this.responseParser.initialize(__http_common.HTTPParser.RESPONSE, {}); + this.responseParser[__http_common.HTTPParser.kOnHeadersComplete] = this.onResponseStart.bind(this); + this.responseParser[__http_common.HTTPParser.kOnBody] = this.onResponseBody.bind(this); + this.responseParser[__http_common.HTTPParser.kOnMessageComplete] = this.onResponseEnd.bind(this); + this.once("finish", () => this.requestParser.free()); + if (this.baseUrl.protocol === "https:") { + Reflect.set(this, "encrypted", true); + Reflect.set(this, "authorized", false); + Reflect.set(this, "getProtocol", () => "TLSv1.3"); + Reflect.set(this, "getSession", () => void 0); + Reflect.set(this, "isSessionReused", () => false); + } + } + emit(event, ...args) { + const emitEvent = super.emit.bind(this, event, ...args); + if (this.responseListenersPromise) { + this.responseListenersPromise.finally(emitEvent); + return this.listenerCount(event) > 0; + } + return emitEvent(); + } + destroy(error) { + this.responseParser.free(); + if (error) { + this.emit("error", error); + } + return super.destroy(error); + } + /** + * Establish this Socket connection as-is and pipe + * its data/events through this Socket. + */ + passthrough() { + this.socketState = "passthrough"; + if (this.destroyed) { + return; + } + const socket = this.createConnection(); + this.originalSocket = socket; + this.once("error", (error) => { + socket.destroy(error); + }); + this.address = socket.address.bind(socket); + let writeArgs; + let headersWritten = false; + while (writeArgs = this.writeBuffer.shift()) { + if (writeArgs !== void 0) { + if (!headersWritten) { + const [chunk, encoding, callback] = writeArgs; + const chunkString = chunk.toString(); + const chunkBeforeRequestHeaders = chunkString.slice( + 0, + chunkString.indexOf("\r\n") + 2 + ); + const chunkAfterRequestHeaders = chunkString.slice( + chunk.indexOf("\r\n\r\n") + ); + const rawRequestHeaders = getRawFetchHeaders(this.request.headers); + const requestHeadersString = rawRequestHeaders.filter(([name]) => { + return name.toLowerCase() !== _chunkWZTE4PCOjs.INTERNAL_REQUEST_ID_HEADER_NAME; + }).map(([name, value]) => `${name}: ${value}`).join("\r\n"); + const headersChunk = `${chunkBeforeRequestHeaders}${requestHeadersString}${chunkAfterRequestHeaders}`; + socket.write(headersChunk, encoding, callback); + headersWritten = true; + continue; + } + socket.write(...writeArgs); + } + } + if (Reflect.get(socket, "encrypted")) { + const tlsProperties = [ + "encrypted", + "authorized", + "getProtocol", + "getSession", + "isSessionReused" + ]; + tlsProperties.forEach((propertyName) => { + Object.defineProperty(this, propertyName, { + enumerable: true, + get: () => { + const value = Reflect.get(socket, propertyName); + return typeof value === "function" ? value.bind(socket) : value; + } + }); + }); + } + socket.on("lookup", (...args) => this.emit("lookup", ...args)).on("connect", () => { + this.connecting = socket.connecting; + this.emit("connect"); + }).on("secureConnect", () => this.emit("secureConnect")).on("secure", () => this.emit("secure")).on("session", (session) => this.emit("session", session)).on("ready", () => this.emit("ready")).on("drain", () => this.emit("drain")).on("data", (chunk) => { + this.push(chunk); + }).on("error", (error) => { + Reflect.set(this, "_hadError", Reflect.get(socket, "_hadError")); + this.emit("error", error); + }).on("resume", () => this.emit("resume")).on("timeout", () => this.emit("timeout")).on("prefinish", () => this.emit("prefinish")).on("finish", () => this.emit("finish")).on("close", (hadError) => this.emit("close", hadError)).on("end", () => this.emit("end")); + } + /** + * Convert the given Fetch API `Response` instance to an + * HTTP message and push it to the socket. + */ + async respondWith(response) { + var _a; + if (this.destroyed) { + return; + } + if (_chunk6L3PFBGTjs.isPropertyAccessible.call(void 0, response, "type") && response.type === "error") { + this.errorWith(new TypeError("Network error")); + return; + } + this.mockConnect(); + this.socketState = "mock"; + this.flushWriteBuffer(); + const serverResponse = new (0, _http.ServerResponse)(new (0, _http.IncomingMessage)(this)); + serverResponse.assignSocket( + new MockSocket({ + write: (chunk, encoding, callback) => { + this.push(chunk, encoding); + callback == null ? void 0 : callback(); + }, + read() { + } + }) + ); + serverResponse.removeHeader("connection"); + serverResponse.removeHeader("date"); + const rawResponseHeaders = getRawFetchHeaders(response.headers); + serverResponse.writeHead( + response.status, + response.statusText || _http.STATUS_CODES[response.status], + rawResponseHeaders + ); + this.once("error", () => { + serverResponse.destroy(); + }); + if (response.body) { + try { + const reader = response.body.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + serverResponse.end(); + break; + } + serverResponse.write(value); + } + } catch (error) { + this.respondWith(_chunk6L3PFBGTjs.createServerErrorResponse.call(void 0, error)); + return; + } + } else { + serverResponse.end(); + } + if (!this.shouldKeepAlive) { + this.emit("readable"); + (_a = this.responseStream) == null ? void 0 : _a.push(null); + this.push(null); + } + } + /** + * Close this socket connection with the given error. + */ + errorWith(error) { + this.destroy(error); + } + mockConnect() { + this.connecting = false; + const isIPv6 = _net2.default.isIPv6(this.connectionOptions.hostname) || this.connectionOptions.family === 6; + const addressInfo = { + address: isIPv6 ? "::1" : "127.0.0.1", + family: isIPv6 ? "IPv6" : "IPv4", + port: this.connectionOptions.port + }; + this.address = () => addressInfo; + this.emit( + "lookup", + null, + addressInfo.address, + addressInfo.family === "IPv6" ? 6 : 4, + this.connectionOptions.host + ); + this.emit("connect"); + this.emit("ready"); + if (this.baseUrl.protocol === "https:") { + this.emit("secure"); + this.emit("secureConnect"); + this.emit( + "session", + this.connectionOptions.session || Buffer.from("mock-session-renegotiate") + ); + this.emit("session", Buffer.from("mock-session-resume")); + } + } + flushWriteBuffer() { + for (const writeCall of this.writeBuffer) { + if (typeof writeCall[2] === "function") { + writeCall[2](); + writeCall[2] = void 0; + } + } + } + onRequestBody(chunk) { + _outvariant.invariant.call(void 0, + this.requestStream, + "Failed to write to a request stream: stream does not exist" + ); + this.requestStream.push(chunk); + } + onRequestEnd() { + if (this.requestStream) { + this.requestStream.push(null); + } + } + onResponseBody(chunk) { + _outvariant.invariant.call(void 0, + this.responseStream, + "Failed to write to a response stream: stream does not exist" + ); + this.responseStream.push(chunk); + } + onResponseEnd() { + if (this.responseStream) { + this.responseStream.push(null); + } + } +}; + +// src/interceptors/ClientRequest/agents.ts + + +var MockAgent = class extends _http2.default.Agent { + constructor(options) { + super(); + this.customAgent = options.customAgent; + this.onRequest = options.onRequest; + this.onResponse = options.onResponse; + } + createConnection(options, callback) { + const createConnection = this.customAgent instanceof _http2.default.Agent && this.customAgent.createConnection || super.createConnection; + const socket = new MockHttpSocket({ + connectionOptions: options, + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), + onRequest: this.onRequest.bind(this), + onResponse: this.onResponse.bind(this) + }); + return socket; + } +}; +var MockHttpsAgent = class extends _https2.default.Agent { + constructor(options) { + super(); + this.customAgent = options.customAgent; + this.onRequest = options.onRequest; + this.onResponse = options.onResponse; + } + createConnection(options, callback) { + const createConnection = this.customAgent instanceof _https2.default.Agent && this.customAgent.createConnection || super.createConnection; + const socket = new MockHttpSocket({ + connectionOptions: options, + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), + onRequest: this.onRequest.bind(this), + onResponse: this.onResponse.bind(this) + }); + return socket; + } +}; + +// src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +var _url = require('url'); + + + + + + + + + + + + +var _logger = require('@open-draft/logger'); + +// src/utils/getUrlByRequestOptions.ts + + +var logger = new (0, _logger.Logger)("utils getUrlByRequestOptions"); +var DEFAULT_PATH = "/"; +var DEFAULT_PROTOCOL = "http:"; +var DEFAULT_HOSTNAME = "localhost"; +var SSL_PORT = 443; +function getAgent(options) { + return options.agent instanceof _http.Agent ? options.agent : void 0; +} +function getProtocolByRequestOptions(options) { + var _a; + if (options.protocol) { + return options.protocol; + } + const agent = getAgent(options); + const agentProtocol = agent == null ? void 0 : agent.protocol; + if (agentProtocol) { + return agentProtocol; + } + const port = getPortByRequestOptions(options); + const isSecureRequest = options.cert || port === SSL_PORT; + return isSecureRequest ? "https:" : ((_a = options.uri) == null ? void 0 : _a.protocol) || DEFAULT_PROTOCOL; +} +function getPortByRequestOptions(options) { + if (options.port) { + return Number(options.port); + } + const agent = getAgent(options); + if (agent == null ? void 0 : agent.options.port) { + return Number(agent.options.port); + } + if (agent == null ? void 0 : agent.defaultPort) { + return Number(agent.defaultPort); + } + return void 0; +} +function getAuthByRequestOptions(options) { + if (options.auth) { + const [username, password] = options.auth.split(":"); + return { username, password }; + } +} +function isRawIPv6Address(host) { + return host.includes(":") && !host.startsWith("[") && !host.endsWith("]"); +} +function getHostname(options) { + let host = options.hostname || options.host; + if (host) { + if (isRawIPv6Address(host)) { + host = `[${host}]`; + } + return new URL(`http://${host}`).hostname; + } + return DEFAULT_HOSTNAME; +} +function getUrlByRequestOptions(options) { + logger.info("request options", options); + if (options.uri) { + logger.info( + 'constructing url from explicitly provided "options.uri": %s', + options.uri + ); + return new URL(options.uri.href); + } + logger.info("figuring out url from request options..."); + const protocol = getProtocolByRequestOptions(options); + logger.info("protocol", protocol); + const port = getPortByRequestOptions(options); + logger.info("port", port); + const hostname = getHostname(options); + logger.info("hostname", hostname); + const path = options.path || DEFAULT_PATH; + logger.info("path", path); + const credentials = getAuthByRequestOptions(options); + logger.info("credentials", credentials); + const authString = credentials ? `${credentials.username}:${credentials.password}@` : ""; + logger.info("auth string:", authString); + const portString = typeof port !== "undefined" ? `:${port}` : ""; + const url = new URL(`${protocol}//${hostname}${portString}${path}`); + url.username = (credentials == null ? void 0 : credentials.username) || ""; + url.password = (credentials == null ? void 0 : credentials.password) || ""; + logger.info("created url:", url); + return url; +} + +// src/utils/cloneObject.ts + +var logger2 = new (0, _logger.Logger)("cloneObject"); +function isPlainObject(obj) { + var _a; + logger2.info("is plain object?", obj); + if (obj == null || !((_a = obj.constructor) == null ? void 0 : _a.name)) { + logger2.info("given object is undefined, not a plain object..."); + return false; + } + logger2.info("checking the object constructor:", obj.constructor.name); + return obj.constructor.name === "Object"; +} +function cloneObject(obj) { + logger2.info("cloning object:", obj); + const enumerableProperties = Object.entries(obj).reduce( + (acc, [key, value]) => { + logger2.info("analyzing key-value pair:", key, value); + acc[key] = isPlainObject(value) ? cloneObject(value) : value; + return acc; + }, + {} + ); + return isPlainObject(obj) ? enumerableProperties : Object.assign(Object.getPrototypeOf(obj), enumerableProperties); +} + +// src/utils/isObject.ts +function isObject(value, loose = false) { + return loose ? Object.prototype.toString.call(value).startsWith("[object ") : Object.prototype.toString.call(value) === "[object Object]"; +} + +// src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +var logger3 = new (0, _logger.Logger)("http normalizeClientRequestArgs"); +function resolveRequestOptions(args, url) { + if (typeof args[1] === "undefined" || typeof args[1] === "function") { + logger3.info("request options not provided, deriving from the url", url); + return _url.urlToHttpOptions.call(void 0, url); + } + if (args[1]) { + logger3.info("has custom RequestOptions!", args[1]); + const requestOptionsFromUrl = _url.urlToHttpOptions.call(void 0, url); + logger3.info("derived RequestOptions from the URL:", requestOptionsFromUrl); + logger3.info("cloning RequestOptions..."); + const clonedRequestOptions = cloneObject(args[1]); + logger3.info("successfully cloned RequestOptions!", clonedRequestOptions); + return { + ...requestOptionsFromUrl, + ...clonedRequestOptions + }; + } + logger3.info("using an empty object as request options"); + return {}; +} +function overrideUrlByRequestOptions(url, options) { + url.host = options.host || url.host; + url.hostname = options.hostname || url.hostname; + url.port = options.port ? options.port.toString() : url.port; + if (options.path) { + const parsedOptionsPath = _url.parse.call(void 0, options.path, false); + url.pathname = parsedOptionsPath.pathname || ""; + url.search = parsedOptionsPath.search || ""; + } + return url; +} +function resolveCallback(args) { + return typeof args[1] === "function" ? args[1] : args[2]; +} +function normalizeClientRequestArgs(defaultProtocol, args) { + let url; + let options; + let callback; + logger3.info("arguments", args); + logger3.info("using default protocol:", defaultProtocol); + if (args.length === 0) { + const url2 = new (0, _url.URL)("http://localhost"); + const options2 = resolveRequestOptions(args, url2); + return [url2, options2]; + } + if (typeof args[0] === "string") { + logger3.info("first argument is a location string:", args[0]); + url = new (0, _url.URL)(args[0]); + logger3.info("created a url:", url); + const requestOptionsFromUrl = _url.urlToHttpOptions.call(void 0, url); + logger3.info("request options from url:", requestOptionsFromUrl); + options = resolveRequestOptions(args, url); + logger3.info("resolved request options:", options); + callback = resolveCallback(args); + } else if (args[0] instanceof _url.URL) { + url = args[0]; + logger3.info("first argument is a URL:", url); + if (typeof args[1] !== "undefined" && isObject(args[1])) { + url = overrideUrlByRequestOptions(url, args[1]); + } + options = resolveRequestOptions(args, url); + logger3.info("derived request options:", options); + callback = resolveCallback(args); + } else if ("hash" in args[0] && !("method" in args[0])) { + const [legacyUrl] = args; + logger3.info("first argument is a legacy URL:", legacyUrl); + if (legacyUrl.hostname === null) { + logger3.info("given legacy URL is relative (no hostname)"); + return isObject(args[1]) ? normalizeClientRequestArgs(defaultProtocol, [ + { path: legacyUrl.path, ...args[1] }, + args[2] + ]) : normalizeClientRequestArgs(defaultProtocol, [ + { path: legacyUrl.path }, + args[1] + ]); + } + logger3.info("given legacy url is absolute"); + const resolvedUrl = new (0, _url.URL)(legacyUrl.href); + return args[1] === void 0 ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl]) : typeof args[1] === "function" ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl, args[1]]) : normalizeClientRequestArgs(defaultProtocol, [ + resolvedUrl, + args[1], + args[2] + ]); + } else if (isObject(args[0])) { + options = { ...args[0] }; + logger3.info("first argument is RequestOptions:", options); + options.protocol = options.protocol || defaultProtocol; + logger3.info("normalized request options:", options); + url = getUrlByRequestOptions(options); + logger3.info("created a URL from RequestOptions:", url.href); + callback = resolveCallback(args); + } else { + throw new Error( + `Failed to construct ClientRequest with these parameters: ${args}` + ); + } + options.protocol = options.protocol || url.protocol; + options.method = options.method || "GET"; + if (typeof options.agent === "undefined") { + const agent = options.protocol === "https:" ? new (0, _https.Agent)({ + rejectUnauthorized: options.rejectUnauthorized + }) : new (0, _http.Agent)(); + options.agent = agent; + logger3.info("resolved fallback agent:", agent); + } + if (!options._defaultAgent) { + logger3.info( + 'has no default agent, setting the default agent for "%s"', + options.protocol + ); + options._defaultAgent = options.protocol === "https:" ? _https.globalAgent : _http.globalAgent; + } + logger3.info("successfully resolved url:", url.href); + logger3.info("successfully resolved options:", options); + logger3.info("successfully resolved callback:", callback); + if (!(url instanceof _url.URL)) { + url = url.toString(); + } + return [url, options, callback]; +} + +// src/interceptors/ClientRequest/index.ts +var _ClientRequestInterceptor = class extends _chunkWZTE4PCOjs.Interceptor { + constructor() { + super(_ClientRequestInterceptor.symbol); + this.onRequest = async ({ + request, + socket + }) => { + const requestId = Reflect.get(request, kRequestId); + const controller = new (0, _chunk6L3PFBGTjs.RequestController)(request); + const isRequestHandled = await _chunk6L3PFBGTjs.handleRequest.call(void 0, { + request, + requestId, + controller, + emitter: this.emitter, + onResponse: (response) => { + socket.respondWith(response); + }, + onRequestError: (response) => { + socket.respondWith(response); + }, + onError: (error) => { + if (error instanceof Error) { + socket.errorWith(error); + } + } + }); + if (!isRequestHandled) { + return socket.passthrough(); + } + }; + this.onResponse = async ({ + requestId, + request, + response, + isMockedResponse + }) => { + return _chunk6L3PFBGTjs.emitAsync.call(void 0, this.emitter, "response", { + requestId, + request, + response, + isMockedResponse + }); + }; + } + setup() { + const { get: originalGet, request: originalRequest } = _http2.default; + const { get: originalHttpsGet, request: originalHttpsRequest } = _https2.default; + const onRequest = this.onRequest.bind(this); + const onResponse = this.onResponse.bind(this); + _http2.default.request = new Proxy(_http2.default.request, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "http:", + args + ); + const mockAgent = new MockAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + _http2.default.get = new Proxy(_http2.default.get, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "http:", + args + ); + const mockAgent = new MockAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + _https2.default.request = new Proxy(_https2.default.request, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "https:", + args + ); + const mockAgent = new MockHttpsAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + _https2.default.get = new Proxy(_https2.default.get, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "https:", + args + ); + const mockAgent = new MockHttpsAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + recordRawFetchHeaders(); + this.subscriptions.push(() => { + _http2.default.get = originalGet; + _http2.default.request = originalRequest; + _https2.default.get = originalHttpsGet; + _https2.default.request = originalHttpsRequest; + restoreHeadersPrototype(); + }); + } +}; +var ClientRequestInterceptor = _ClientRequestInterceptor; +ClientRequestInterceptor.symbol = Symbol("client-request-interceptor"); + + + +exports.ClientRequestInterceptor = ClientRequestInterceptor; +//# sourceMappingURL=chunk-4IGRW7SK.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-4IGRW7SK.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-4IGRW7SK.js.map new file mode 100644 index 0000000000..234db51d79 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-4IGRW7SK.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/ClientRequest/index.ts","../../src/interceptors/ClientRequest/MockHttpSocket.ts","../../src/interceptors/Socket/MockSocket.ts","../../src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts","../../src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts","../../src/interceptors/ClientRequest/utils/recordRawHeaders.ts","../../src/interceptors/ClientRequest/agents.ts","../../src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts","../../src/utils/getUrlByRequestOptions.ts","../../src/utils/cloneObject.ts","../../src/utils/isObject.ts"],"names":["http","https","net","headers","URL","Logger","logger","url","options"],"mappings":"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","sourcesContent":["import http from 'node:http'\nimport https from 'node:https'\nimport { Interceptor } from '../../Interceptor'\nimport type { HttpRequestEventMap } from '../../glossary'\nimport {\n kRequestId,\n MockHttpSocketRequestCallback,\n MockHttpSocketResponseCallback,\n} from './MockHttpSocket'\nimport { MockAgent, MockHttpsAgent } from './agents'\nimport { RequestController } from '../../RequestController'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { normalizeClientRequestArgs } from './utils/normalizeClientRequestArgs'\nimport { handleRequest } from '../../utils/handleRequest'\nimport {\n recordRawFetchHeaders,\n restoreHeadersPrototype,\n} from './utils/recordRawHeaders'\n\nexport class ClientRequestInterceptor extends Interceptor {\n static symbol = Symbol('client-request-interceptor')\n\n constructor() {\n super(ClientRequestInterceptor.symbol)\n }\n\n protected setup(): void {\n const { get: originalGet, request: originalRequest } = http\n const { get: originalHttpsGet, request: originalHttpsRequest } = https\n\n const onRequest = this.onRequest.bind(this)\n const onResponse = this.onResponse.bind(this)\n\n http.request = new Proxy(http.request, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'http:',\n args\n )\n const mockAgent = new MockAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n http.get = new Proxy(http.get, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'http:',\n args\n )\n\n const mockAgent = new MockAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n //\n // HTTPS.\n //\n\n https.request = new Proxy(https.request, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'https:',\n args\n )\n\n const mockAgent = new MockHttpsAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n https.get = new Proxy(https.get, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'https:',\n args\n )\n\n const mockAgent = new MockHttpsAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n // Spy on `Header.prototype.set` and `Header.prototype.append` calls\n // and record the raw header names provided. This is to support\n // `IncomingMessage.prototype.rawHeaders`.\n recordRawFetchHeaders()\n\n this.subscriptions.push(() => {\n http.get = originalGet\n http.request = originalRequest\n\n https.get = originalHttpsGet\n https.request = originalHttpsRequest\n\n restoreHeadersPrototype()\n })\n }\n\n private onRequest: MockHttpSocketRequestCallback = async ({\n request,\n socket,\n }) => {\n const requestId = Reflect.get(request, kRequestId)\n const controller = new RequestController(request)\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n controller,\n emitter: this.emitter,\n onResponse: (response) => {\n socket.respondWith(response)\n },\n onRequestError: (response) => {\n socket.respondWith(response)\n },\n onError: (error) => {\n if (error instanceof Error) {\n socket.errorWith(error)\n }\n },\n })\n\n if (!isRequestHandled) {\n return socket.passthrough()\n }\n }\n\n public onResponse: MockHttpSocketResponseCallback = async ({\n requestId,\n request,\n response,\n isMockedResponse,\n }) => {\n // Return the promise to when all the response event listeners\n // are finished.\n return emitAsync(this.emitter, 'response', {\n requestId,\n request,\n response,\n isMockedResponse,\n })\n }\n}\n","import net from 'node:net'\nimport {\n HTTPParser,\n type RequestHeadersCompleteCallback,\n type ResponseHeadersCompleteCallback,\n} from '_http_common'\nimport { STATUS_CODES, IncomingMessage, ServerResponse } from 'node:http'\nimport { Readable } from 'node:stream'\nimport { invariant } from 'outvariant'\nimport { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'\nimport { MockSocket } from '../Socket/MockSocket'\nimport type { NormalizedSocketWriteArgs } from '../Socket/utils/normalizeSocketWriteArgs'\nimport { isPropertyAccessible } from '../../utils/isPropertyAccessible'\nimport { baseUrlFromConnectionOptions } from '../Socket/utils/baseUrlFromConnectionOptions'\nimport { createServerErrorResponse } from '../../utils/responseUtils'\nimport { createRequestId } from '../../createRequestId'\nimport { getRawFetchHeaders } from './utils/recordRawHeaders'\nimport { FetchResponse } from '../../utils/fetchUtils'\n\ntype HttpConnectionOptions = any\n\nexport type MockHttpSocketRequestCallback = (args: {\n requestId: string\n request: Request\n socket: MockHttpSocket\n}) => void\n\nexport type MockHttpSocketResponseCallback = (args: {\n requestId: string\n request: Request\n response: Response\n isMockedResponse: boolean\n socket: MockHttpSocket\n}) => Promise\n\ninterface MockHttpSocketOptions {\n connectionOptions: HttpConnectionOptions\n createConnection: () => net.Socket\n onRequest: MockHttpSocketRequestCallback\n onResponse: MockHttpSocketResponseCallback\n}\n\nexport const kRequestId = Symbol('kRequestId')\n\nexport class MockHttpSocket extends MockSocket {\n private connectionOptions: HttpConnectionOptions\n private createConnection: () => net.Socket\n private baseUrl: URL\n\n private onRequest: MockHttpSocketRequestCallback\n private onResponse: MockHttpSocketResponseCallback\n private responseListenersPromise?: Promise\n\n private writeBuffer: Array = []\n private request?: Request\n private requestParser: HTTPParser<0>\n private requestStream?: Readable\n private shouldKeepAlive?: boolean\n\n private socketState: 'unknown' | 'mock' | 'passthrough' = 'unknown'\n private responseParser: HTTPParser<1>\n private responseStream?: Readable\n private originalSocket?: net.Socket\n\n constructor(options: MockHttpSocketOptions) {\n super({\n write: (chunk, encoding, callback) => {\n // Buffer the writes so they can be flushed in case of the original connection\n // and when reading the request body in the interceptor. If the connection has\n // been established, no need to buffer the chunks anymore, they will be forwarded.\n if (this.socketState !== 'passthrough') {\n this.writeBuffer.push([chunk, encoding, callback])\n }\n\n if (chunk) {\n /**\n * Forward any writes to the mock socket to the underlying original socket.\n * This ensures functional duplex connections, like WebSocket.\n * @see https://github.com/mswjs/interceptors/issues/682\n */\n if (this.socketState === 'passthrough') {\n this.originalSocket?.write(chunk, encoding, callback)\n }\n\n this.requestParser.execute(\n Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding)\n )\n }\n },\n read: (chunk) => {\n if (chunk !== null) {\n /**\n * @todo We need to free the parser if the connection has been\n * upgraded to a non-HTTP protocol. It won't be able to parse data\n * from that point onward anyway. No need to keep it in memory.\n */\n this.responseParser.execute(\n Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n )\n }\n },\n })\n\n this.connectionOptions = options.connectionOptions\n this.createConnection = options.createConnection\n this.onRequest = options.onRequest\n this.onResponse = options.onResponse\n\n this.baseUrl = baseUrlFromConnectionOptions(this.connectionOptions)\n\n // Request parser.\n this.requestParser = new HTTPParser()\n this.requestParser.initialize(HTTPParser.REQUEST, {})\n this.requestParser[HTTPParser.kOnHeadersComplete] =\n this.onRequestStart.bind(this)\n this.requestParser[HTTPParser.kOnBody] = this.onRequestBody.bind(this)\n this.requestParser[HTTPParser.kOnMessageComplete] =\n this.onRequestEnd.bind(this)\n\n // Response parser.\n this.responseParser = new HTTPParser()\n this.responseParser.initialize(HTTPParser.RESPONSE, {})\n this.responseParser[HTTPParser.kOnHeadersComplete] =\n this.onResponseStart.bind(this)\n this.responseParser[HTTPParser.kOnBody] = this.onResponseBody.bind(this)\n this.responseParser[HTTPParser.kOnMessageComplete] =\n this.onResponseEnd.bind(this)\n\n // Once the socket is finished, nothing can write to it\n // anymore. It has also flushed any buffered chunks.\n this.once('finish', () => this.requestParser.free())\n\n if (this.baseUrl.protocol === 'https:') {\n Reflect.set(this, 'encrypted', true)\n // The server certificate is not the same as a CA\n // passed to the TLS socket connection options.\n Reflect.set(this, 'authorized', false)\n Reflect.set(this, 'getProtocol', () => 'TLSv1.3')\n Reflect.set(this, 'getSession', () => undefined)\n Reflect.set(this, 'isSessionReused', () => false)\n }\n }\n\n public emit(event: string | symbol, ...args: any[]): boolean {\n const emitEvent = super.emit.bind(this, event as any, ...args)\n\n if (this.responseListenersPromise) {\n this.responseListenersPromise.finally(emitEvent)\n return this.listenerCount(event) > 0\n }\n\n return emitEvent()\n }\n\n public destroy(error?: Error | undefined): this {\n // Destroy the response parser when the socket gets destroyed.\n // Normally, we shoud listen to the \"close\" event but it\n // can be suppressed by using the \"emitClose: false\" option.\n this.responseParser.free()\n\n if (error) {\n this.emit('error', error)\n }\n\n return super.destroy(error)\n }\n\n /**\n * Establish this Socket connection as-is and pipe\n * its data/events through this Socket.\n */\n public passthrough(): void {\n this.socketState = 'passthrough'\n\n if (this.destroyed) {\n return\n }\n\n const socket = this.createConnection()\n this.originalSocket = socket\n\n // If the developer destroys the socket, destroy the original connection.\n this.once('error', (error) => {\n socket.destroy(error)\n })\n\n this.address = socket.address.bind(socket)\n\n // Flush the buffered \"socket.write()\" calls onto\n // the original socket instance (i.e. write request body).\n // Exhaust the \"requestBuffer\" in case this Socket\n // gets reused for different requests.\n let writeArgs: NormalizedSocketWriteArgs | undefined\n let headersWritten = false\n\n while ((writeArgs = this.writeBuffer.shift())) {\n if (writeArgs !== undefined) {\n if (!headersWritten) {\n const [chunk, encoding, callback] = writeArgs\n const chunkString = chunk.toString()\n const chunkBeforeRequestHeaders = chunkString.slice(\n 0,\n chunkString.indexOf('\\r\\n') + 2\n )\n const chunkAfterRequestHeaders = chunkString.slice(\n chunk.indexOf('\\r\\n\\r\\n')\n )\n const rawRequestHeaders = getRawFetchHeaders(this.request!.headers)\n const requestHeadersString = rawRequestHeaders\n // Skip the internal request ID deduplication header.\n .filter(([name]) => {\n return name.toLowerCase() !== INTERNAL_REQUEST_ID_HEADER_NAME\n })\n .map(([name, value]) => `${name}: ${value}`)\n .join('\\r\\n')\n\n // Modify the HTTP request message headers\n // to reflect any changes to the request headers\n // from the \"request\" event listener.\n const headersChunk = `${chunkBeforeRequestHeaders}${requestHeadersString}${chunkAfterRequestHeaders}`\n socket.write(headersChunk, encoding, callback)\n headersWritten = true\n continue\n }\n\n socket.write(...writeArgs)\n }\n }\n\n // Forward TLS Socket properties onto this Socket instance\n // in the case of a TLS/SSL connection.\n if (Reflect.get(socket, 'encrypted')) {\n const tlsProperties = [\n 'encrypted',\n 'authorized',\n 'getProtocol',\n 'getSession',\n 'isSessionReused',\n ]\n\n tlsProperties.forEach((propertyName) => {\n Object.defineProperty(this, propertyName, {\n enumerable: true,\n get: () => {\n const value = Reflect.get(socket, propertyName)\n return typeof value === 'function' ? value.bind(socket) : value\n },\n })\n })\n }\n\n socket\n .on('lookup', (...args) => this.emit('lookup', ...args))\n .on('connect', () => {\n this.connecting = socket.connecting\n this.emit('connect')\n })\n .on('secureConnect', () => this.emit('secureConnect'))\n .on('secure', () => this.emit('secure'))\n .on('session', (session) => this.emit('session', session))\n .on('ready', () => this.emit('ready'))\n .on('drain', () => this.emit('drain'))\n .on('data', (chunk) => {\n // Push the original response to this socket\n // so it triggers the HTTP response parser. This unifies\n // the handling pipeline for original and mocked response.\n this.push(chunk)\n })\n .on('error', (error) => {\n Reflect.set(this, '_hadError', Reflect.get(socket, '_hadError'))\n this.emit('error', error)\n })\n .on('resume', () => this.emit('resume'))\n .on('timeout', () => this.emit('timeout'))\n .on('prefinish', () => this.emit('prefinish'))\n .on('finish', () => this.emit('finish'))\n .on('close', (hadError) => this.emit('close', hadError))\n .on('end', () => this.emit('end'))\n }\n\n /**\n * Convert the given Fetch API `Response` instance to an\n * HTTP message and push it to the socket.\n */\n public async respondWith(response: Response): Promise {\n // Ignore the mocked response if the socket has been destroyed\n // (e.g. aborted or timed out),\n if (this.destroyed) {\n return\n }\n\n // Handle \"type: error\" responses.\n if (isPropertyAccessible(response, 'type') && response.type === 'error') {\n this.errorWith(new TypeError('Network error'))\n return\n }\n\n // First, emit all the connection events\n // to emulate a successful connection.\n this.mockConnect()\n this.socketState = 'mock'\n\n // Flush the write buffer to trigger write callbacks\n // if it hasn't been flushed already (e.g. someone started reading request stream).\n this.flushWriteBuffer()\n\n // Create a `ServerResponse` instance to delegate HTTP message parsing,\n // Transfer-Encoding, and other things to Node.js internals.\n const serverResponse = new ServerResponse(new IncomingMessage(this))\n\n /**\n * Assign a mock socket instance to the server response to\n * spy on the response chunk writes. Push the transformed response chunks\n * to this `MockHttpSocket` instance to trigger the \"data\" event.\n * @note Providing the same `MockSocket` instance when creating `ServerResponse`\n * does not have the same effect.\n * @see https://github.com/nodejs/node/blob/10099bb3f7fd97bb9dd9667188426866b3098e07/test/parallel/test-http-server-response-standalone.js#L32\n */\n serverResponse.assignSocket(\n new MockSocket({\n write: (chunk, encoding, callback) => {\n this.push(chunk, encoding)\n callback?.()\n },\n read() {},\n })\n )\n\n /**\n * @note Remove the `Connection` and `Date` response headers\n * injected by `ServerResponse` by default. Those are required\n * from the server but the interceptor is NOT technically a server.\n * It's confusing to add response headers that the developer didn't\n * specify themselves. They can always add these if they wish.\n * @see https://www.rfc-editor.org/rfc/rfc9110#field.date\n * @see https://www.rfc-editor.org/rfc/rfc9110#field.connection\n */\n serverResponse.removeHeader('connection')\n serverResponse.removeHeader('date')\n\n const rawResponseHeaders = getRawFetchHeaders(response.headers)\n\n /**\n * @note Call `.writeHead` in order to set the raw response headers\n * in the same case as they were provided by the developer. Using\n * `.setHeader()`/`.appendHeader()` normalizes header names.\n */\n serverResponse.writeHead(\n response.status,\n response.statusText || STATUS_CODES[response.status],\n rawResponseHeaders\n )\n\n // If the developer destroy the socket, gracefully destroy the response.\n this.once('error', () => {\n serverResponse.destroy()\n })\n\n if (response.body) {\n try {\n const reader = response.body.getReader()\n\n while (true) {\n const { done, value } = await reader.read()\n\n if (done) {\n serverResponse.end()\n break\n }\n\n serverResponse.write(value)\n }\n } catch (error) {\n // Coerce response stream errors to 500 responses.\n this.respondWith(createServerErrorResponse(error))\n return\n }\n } else {\n serverResponse.end()\n }\n\n // Close the socket if the connection wasn't marked as keep-alive.\n if (!this.shouldKeepAlive) {\n this.emit('readable')\n\n /**\n * @todo @fixme This is likely a hack.\n * Since we push null to the socket, it never propagates to the\n * parser, and the parser never calls \"onResponseEnd\" to close\n * the response stream. We are closing the stream here manually\n * but that shouldn't be the case.\n */\n this.responseStream?.push(null)\n this.push(null)\n }\n }\n\n /**\n * Close this socket connection with the given error.\n */\n public errorWith(error?: Error): void {\n this.destroy(error)\n }\n\n private mockConnect(): void {\n // Calling this method immediately puts the socket\n // into the connected state.\n this.connecting = false\n\n const isIPv6 =\n net.isIPv6(this.connectionOptions.hostname) ||\n this.connectionOptions.family === 6\n const addressInfo = {\n address: isIPv6 ? '::1' : '127.0.0.1',\n family: isIPv6 ? 'IPv6' : 'IPv4',\n port: this.connectionOptions.port,\n }\n // Return fake address information for the socket.\n this.address = () => addressInfo\n this.emit(\n 'lookup',\n null,\n addressInfo.address,\n addressInfo.family === 'IPv6' ? 6 : 4,\n this.connectionOptions.host\n )\n this.emit('connect')\n this.emit('ready')\n\n if (this.baseUrl.protocol === 'https:') {\n this.emit('secure')\n this.emit('secureConnect')\n\n // A single TLS connection is represented by two \"session\" events.\n this.emit(\n 'session',\n this.connectionOptions.session ||\n Buffer.from('mock-session-renegotiate')\n )\n this.emit('session', Buffer.from('mock-session-resume'))\n }\n }\n\n private flushWriteBuffer(): void {\n for (const writeCall of this.writeBuffer) {\n if (typeof writeCall[2] === 'function') {\n writeCall[2]()\n /**\n * @note Remove the callback from the write call\n * so it doesn't get called twice on passthrough\n * if `request.end()` was called within `request.write()`.\n * @see https://github.com/mswjs/interceptors/issues/684\n */\n writeCall[2] = undefined\n }\n }\n }\n\n private onRequestStart: RequestHeadersCompleteCallback = (\n versionMajor,\n versionMinor,\n rawHeaders,\n _,\n path,\n __,\n ___,\n ____,\n shouldKeepAlive\n ) => {\n this.shouldKeepAlive = shouldKeepAlive\n\n const url = new URL(path, this.baseUrl)\n const method = this.connectionOptions.method?.toUpperCase() || 'GET'\n const headers = FetchResponse.parseRawHeaders(rawHeaders)\n const canHaveBody = method !== 'GET' && method !== 'HEAD'\n\n // Translate the basic authorization in the URL to the request header.\n // Constructing a Request instance with a URL containing auth is no-op.\n if (url.username || url.password) {\n if (!headers.has('authorization')) {\n headers.set('authorization', `Basic ${url.username}:${url.password}`)\n }\n url.username = ''\n url.password = ''\n }\n\n // Create a new stream for each request.\n // If this Socket is reused for multiple requests,\n // this ensures that each request gets its own stream.\n // One Socket instance can only handle one request at a time.\n if (canHaveBody) {\n this.requestStream = new Readable({\n /**\n * @note Provide the `read()` method so a `Readable` could be\n * used as the actual request body (the stream calls \"read()\").\n * We control the queue in the onRequestBody/End functions.\n */\n read: () => {\n // If the user attempts to read the request body,\n // flush the write buffer to trigger the callbacks.\n // This way, if the request stream ends in the write callback,\n // it will indeed end correctly.\n this.flushWriteBuffer()\n },\n })\n }\n\n const requestId = createRequestId()\n this.request = new Request(url, {\n method,\n headers,\n credentials: 'same-origin',\n // @ts-expect-error Undocumented Fetch property.\n duplex: canHaveBody ? 'half' : undefined,\n body: canHaveBody ? (Readable.toWeb(this.requestStream!) as any) : null,\n })\n\n Reflect.set(this.request, kRequestId, requestId)\n\n // Skip handling the request that's already being handled\n // by another (parent) interceptor. For example, XMLHttpRequest\n // is often implemented via ClientRequest in Node.js (e.g. JSDOM).\n // In that case, XHR interceptor will bubble down to the ClientRequest\n // interceptor. No need to try to handle that request again.\n /**\n * @fixme Stop relying on the \"X-Request-Id\" request header\n * to figure out if one interceptor has been invoked within another.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\n if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) {\n this.passthrough()\n return\n }\n\n this.onRequest({\n requestId,\n request: this.request,\n socket: this,\n })\n }\n\n private onRequestBody(chunk: Buffer): void {\n invariant(\n this.requestStream,\n 'Failed to write to a request stream: stream does not exist'\n )\n\n this.requestStream.push(chunk)\n }\n\n private onRequestEnd(): void {\n // Request end can be called for requests without body.\n if (this.requestStream) {\n this.requestStream.push(null)\n }\n }\n\n private onResponseStart: ResponseHeadersCompleteCallback = (\n versionMajor,\n versionMinor,\n rawHeaders,\n method,\n url,\n status,\n statusText\n ) => {\n const headers = FetchResponse.parseRawHeaders(rawHeaders)\n\n const response = new FetchResponse(\n /**\n * @note The Fetch API response instance exposed to the consumer\n * is created over the response stream of the HTTP parser. It is NOT\n * related to the Socket instance. This way, you can read response body\n * in response listener while the Socket instance delays the emission\n * of \"end\" and other events until those response listeners are finished.\n */\n FetchResponse.isResponseWithBody(status)\n ? (Readable.toWeb(\n (this.responseStream = new Readable({ read() {} }))\n ) as any)\n : null,\n {\n url,\n status,\n statusText,\n headers,\n }\n )\n\n invariant(\n this.request,\n 'Failed to handle a response: request does not exist'\n )\n\n /**\n * @fixme Stop relying on the \"X-Request-Id\" request header\n * to figure out if one interceptor has been invoked within another.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\n if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) {\n return\n }\n\n this.responseListenersPromise = this.onResponse({\n response,\n isMockedResponse: this.socketState === 'mock',\n requestId: Reflect.get(this.request, kRequestId),\n request: this.request,\n socket: this,\n })\n }\n\n private onResponseBody(chunk: Buffer) {\n invariant(\n this.responseStream,\n 'Failed to write to a response stream: stream does not exist'\n )\n\n this.responseStream.push(chunk)\n }\n\n private onResponseEnd(): void {\n // Response end can be called for responses without body.\n if (this.responseStream) {\n this.responseStream.push(null)\n }\n }\n}\n","import net from 'node:net'\nimport {\n normalizeSocketWriteArgs,\n type WriteArgs,\n type WriteCallback,\n} from './utils/normalizeSocketWriteArgs'\n\nexport interface MockSocketOptions {\n write: (\n chunk: Buffer | string,\n encoding: BufferEncoding | undefined,\n callback?: WriteCallback\n ) => void\n\n read: (chunk: Buffer, encoding: BufferEncoding | undefined) => void\n}\n\nexport class MockSocket extends net.Socket {\n public connecting: boolean\n\n constructor(protected readonly options: MockSocketOptions) {\n super()\n this.connecting = false\n this.connect()\n\n this._final = (callback) => {\n callback(null)\n }\n }\n\n public connect() {\n // The connection will remain pending until\n // the consumer decides to handle it.\n this.connecting = true\n return this\n }\n\n public write(...args: Array): boolean {\n const [chunk, encoding, callback] = normalizeSocketWriteArgs(\n args as WriteArgs\n )\n this.options.write(chunk, encoding, callback)\n return true\n }\n\n public end(...args: Array) {\n const [chunk, encoding, callback] = normalizeSocketWriteArgs(\n args as WriteArgs\n )\n this.options.write(chunk, encoding, callback)\n return super.end.apply(this, args as any)\n }\n\n public push(chunk: any, encoding?: BufferEncoding): boolean {\n this.options.read(chunk, encoding)\n return super.push(chunk, encoding)\n }\n}\n","export type WriteCallback = (error?: Error | null) => void\n\nexport type WriteArgs =\n | [chunk: unknown, callback?: WriteCallback]\n | [chunk: unknown, encoding: BufferEncoding, callback?: WriteCallback]\n\nexport type NormalizedSocketWriteArgs = [\n chunk: any,\n encoding?: BufferEncoding,\n callback?: WriteCallback,\n]\n\n/**\n * Normalizes the arguments provided to the `Writable.prototype.write()`\n * and `Writable.prototype.end()`.\n */\nexport function normalizeSocketWriteArgs(\n args: WriteArgs\n): NormalizedSocketWriteArgs {\n const normalized: NormalizedSocketWriteArgs = [args[0], undefined, undefined]\n\n if (typeof args[1] === 'string') {\n normalized[1] = args[1]\n } else if (typeof args[1] === 'function') {\n normalized[2] = args[1]\n }\n\n if (typeof args[2] === 'function') {\n normalized[2] = args[2]\n }\n\n return normalized\n}\n","export function baseUrlFromConnectionOptions(options: any): URL {\n if ('href' in options) {\n return new URL(options.href)\n }\n\n const protocol = options.port === 443 ? 'https:' : 'http:'\n const host = options.host\n\n const url = new URL(`${protocol}//${host}`)\n\n if (options.port) {\n url.port = options.port.toString()\n }\n\n if (options.path) {\n url.pathname = options.path\n }\n\n if (options.auth) {\n const [username, password] = options.auth.split(':')\n url.username = username\n url.password = password\n }\n\n return url\n}\n","type HeaderTuple = [string, string]\ntype RawHeaders = Array\ntype SetHeaderBehavior = 'set' | 'append'\n\nconst kRawHeaders = Symbol('kRawHeaders')\nconst kRestorePatches = Symbol('kRestorePatches')\n\nfunction recordRawHeader(\n headers: Headers,\n args: HeaderTuple,\n behavior: SetHeaderBehavior\n) {\n ensureRawHeadersSymbol(headers, [])\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n\n if (behavior === 'set') {\n // When recording a set header, ensure we remove any matching existing headers.\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n rawHeaders.push(args)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, this function does nothing.\n */\nfunction ensureRawHeadersSymbol(\n headers: Headers,\n rawHeaders: RawHeaders\n): void {\n if (Reflect.has(headers, kRawHeaders)) {\n return\n }\n\n defineRawHeadersSymbol(headers, rawHeaders)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, it gets overridden.\n */\nfunction defineRawHeadersSymbol(headers: Headers, rawHeaders: RawHeaders) {\n Object.defineProperty(headers, kRawHeaders, {\n value: rawHeaders,\n enumerable: false,\n // Mark the symbol as configurable so its value can be overridden.\n // Overrides happen when merging raw headers from multiple sources.\n // E.g. new Request(new Request(url, { headers }), { headers })\n configurable: true,\n })\n}\n\n/**\n * Patch the global `Headers` class to store raw headers.\n * This is for compatibility with `IncomingMessage.prototype.rawHeaders`.\n *\n * @note Node.js has their own raw headers symbol but it\n * only records the first header name in case of multi-value headers.\n * Any other headers are normalized before comparing. This makes it\n * incompatible with the `rawHeaders` format.\n *\n * let h = new Headers()\n * h.append('X-Custom', 'one')\n * h.append('x-custom', 'two')\n * h[Symbol('headers map')] // Map { 'X-Custom' => 'one, two' }\n */\nexport function recordRawFetchHeaders() {\n // Prevent patching the Headers prototype multiple times.\n if (Reflect.get(Headers, kRestorePatches)) {\n return Reflect.get(Headers, kRestorePatches)\n }\n\n const {\n Headers: OriginalHeaders,\n Request: OriginalRequest,\n Response: OriginalResponse,\n } = globalThis\n const { set, append, delete: headersDeleteMethod } = Headers.prototype\n\n Object.defineProperty(Headers, kRestorePatches, {\n value: () => {\n Headers.prototype.set = set\n Headers.prototype.append = append\n Headers.prototype.delete = headersDeleteMethod\n globalThis.Headers = OriginalHeaders\n\n globalThis.Request = OriginalRequest\n globalThis.Response = OriginalResponse\n\n Reflect.deleteProperty(Headers, kRestorePatches)\n },\n enumerable: false,\n /**\n * @note Mark this property as configurable\n * so we can delete it using `Reflect.delete` during cleanup.\n */\n configurable: true,\n })\n\n Object.defineProperty(globalThis, 'Headers', {\n enumerable: true,\n writable: true,\n value: new Proxy(Headers, {\n construct(target, args, newTarget) {\n const headersInit = args[0] || []\n\n if (\n headersInit instanceof Headers &&\n Reflect.has(headersInit, kRawHeaders)\n ) {\n const headers = Reflect.construct(\n target,\n [Reflect.get(headersInit, kRawHeaders)],\n newTarget\n )\n ensureRawHeadersSymbol(headers, [\n /**\n * @note Spread the retrieved headers to clone them.\n * This prevents multiple Headers instances from pointing\n * at the same internal \"rawHeaders\" array.\n */\n ...Reflect.get(headersInit, kRawHeaders),\n ])\n return headers\n }\n\n const headers = Reflect.construct(target, args, newTarget)\n\n // Request/Response constructors will set the symbol\n // upon creating a new instance, using the raw developer\n // input as the raw headers. Skip the symbol altogether\n // in those cases because the input to Headers will be normalized.\n if (!Reflect.has(headers, kRawHeaders)) {\n const rawHeadersInit = Array.isArray(headersInit)\n ? headersInit\n : Object.entries(headersInit)\n ensureRawHeadersSymbol(headers, rawHeadersInit)\n }\n\n return headers\n },\n }),\n })\n\n Headers.prototype.set = new Proxy(Headers.prototype.set, {\n apply(target, thisArg, args: HeaderTuple) {\n recordRawHeader(thisArg, args, 'set')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.append = new Proxy(Headers.prototype.append, {\n apply(target, thisArg, args: HeaderTuple) {\n recordRawHeader(thisArg, args, 'append')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.delete = new Proxy(Headers.prototype.delete, {\n apply(target, thisArg, args: [string]) {\n const rawHeaders = Reflect.get(thisArg, kRawHeaders) as RawHeaders\n\n if (rawHeaders) {\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Object.defineProperty(globalThis, 'Request', {\n enumerable: true,\n writable: true,\n value: new Proxy(Request, {\n construct(target, args, newTarget) {\n const request = Reflect.construct(target, args, newTarget)\n const inferredRawHeaders: RawHeaders = []\n\n // Infer raw headers from a `Request` instance used as init.\n if (typeof args[0] === 'object' && args[0].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[0].headers))\n }\n\n // Infer raw headers from the \"headers\" init argument.\n if (typeof args[1] === 'object' && args[1].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[1].headers))\n }\n\n if (inferredRawHeaders.length > 0) {\n ensureRawHeadersSymbol(request.headers, inferredRawHeaders)\n }\n\n return request\n },\n }),\n })\n\n Object.defineProperty(globalThis, 'Response', {\n enumerable: true,\n writable: true,\n value: new Proxy(Response, {\n construct(target, args, newTarget) {\n const response = Reflect.construct(target, args, newTarget)\n\n if (typeof args[1] === 'object' && args[1].headers != null) {\n ensureRawHeadersSymbol(\n response.headers,\n inferRawHeaders(args[1].headers)\n )\n }\n\n return response\n },\n }),\n })\n}\n\nexport function restoreHeadersPrototype() {\n if (!Reflect.get(Headers, kRestorePatches)) {\n return\n }\n\n Reflect.get(Headers, kRestorePatches)()\n}\n\nexport function getRawFetchHeaders(headers: Headers): RawHeaders {\n // If the raw headers recording failed for some reason,\n // use the normalized header entries instead.\n if (!Reflect.has(headers, kRawHeaders)) {\n return Array.from(headers.entries())\n }\n\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries())\n}\n\n/**\n * Infers the raw headers from the given `HeadersInit` provided\n * to the Request/Response constructor.\n *\n * If the `init.headers` is a Headers instance, use it directly.\n * That means the headers were created standalone and already have\n * the raw headers stored.\n * If the `init.headers` is a HeadersInit, create a new Headers\n * instace out of it.\n */\nfunction inferRawHeaders(headers: HeadersInit): RawHeaders {\n if (headers instanceof Headers) {\n return Reflect.get(headers, kRawHeaders) || []\n }\n\n return Reflect.get(new Headers(headers), kRawHeaders)\n}\n","import net from 'node:net'\nimport http from 'node:http'\nimport https from 'node:https'\nimport {\n MockHttpSocket,\n type MockHttpSocketRequestCallback,\n type MockHttpSocketResponseCallback,\n} from './MockHttpSocket'\n\ndeclare module 'node:http' {\n interface Agent {\n createConnection(options: any, callback: any): net.Socket\n }\n}\n\ninterface MockAgentOptions {\n customAgent?: http.RequestOptions['agent']\n onRequest: MockHttpSocketRequestCallback\n onResponse: MockHttpSocketResponseCallback\n}\n\nexport class MockAgent extends http.Agent {\n private customAgent?: http.RequestOptions['agent']\n private onRequest: MockHttpSocketRequestCallback\n private onResponse: MockHttpSocketResponseCallback\n\n constructor(options: MockAgentOptions) {\n super()\n this.customAgent = options.customAgent\n this.onRequest = options.onRequest\n this.onResponse = options.onResponse\n }\n\n public createConnection(options: any, callback: any): net.Socket {\n const createConnection =\n (this.customAgent instanceof http.Agent &&\n this.customAgent.createConnection) ||\n super.createConnection\n\n const socket = new MockHttpSocket({\n connectionOptions: options,\n createConnection: createConnection.bind(\n this.customAgent || this,\n options,\n callback\n ),\n onRequest: this.onRequest.bind(this),\n onResponse: this.onResponse.bind(this),\n })\n\n return socket\n }\n}\n\nexport class MockHttpsAgent extends https.Agent {\n private customAgent?: https.RequestOptions['agent']\n private onRequest: MockHttpSocketRequestCallback\n private onResponse: MockHttpSocketResponseCallback\n\n constructor(options: MockAgentOptions) {\n super()\n this.customAgent = options.customAgent\n this.onRequest = options.onRequest\n this.onResponse = options.onResponse\n }\n\n public createConnection(options: any, callback: any): net.Socket {\n const createConnection =\n (this.customAgent instanceof https.Agent &&\n this.customAgent.createConnection) ||\n super.createConnection\n\n const socket = new MockHttpSocket({\n connectionOptions: options,\n createConnection: createConnection.bind(\n this.customAgent || this,\n options,\n callback\n ),\n onRequest: this.onRequest.bind(this),\n onResponse: this.onResponse.bind(this),\n })\n\n return socket\n }\n}\n","import { urlToHttpOptions } from 'node:url'\nimport {\n Agent as HttpAgent,\n globalAgent as httpGlobalAgent,\n IncomingMessage,\n} from 'node:http'\nimport {\n RequestOptions,\n Agent as HttpsAgent,\n globalAgent as httpsGlobalAgent,\n} from 'node:https'\nimport {\n /**\n * @note Use the Node.js URL instead of the global URL\n * because environments like JSDOM may override the global,\n * breaking the compatibility with Node.js.\n * @see https://github.com/node-fetch/node-fetch/issues/1376#issuecomment-966435555\n */\n URL,\n Url as LegacyURL,\n parse as parseUrl,\n} from 'node:url'\nimport { Logger } from '@open-draft/logger'\nimport {\n ResolvedRequestOptions,\n getUrlByRequestOptions,\n} from '../../../utils/getUrlByRequestOptions'\nimport { cloneObject } from '../../../utils/cloneObject'\nimport { isObject } from '../../../utils/isObject'\n\nconst logger = new Logger('http normalizeClientRequestArgs')\n\nexport type HttpRequestCallback = (response: IncomingMessage) => void\n\nexport type ClientRequestArgs =\n // Request without any arguments is also possible.\n | []\n | [string | URL | LegacyURL, HttpRequestCallback?]\n | [string | URL | LegacyURL, RequestOptions, HttpRequestCallback?]\n | [RequestOptions, HttpRequestCallback?]\n\nfunction resolveRequestOptions(\n args: ClientRequestArgs,\n url: URL\n): RequestOptions {\n // Calling `fetch` provides only URL to `ClientRequest`\n // without any `RequestOptions` or callback.\n if (typeof args[1] === 'undefined' || typeof args[1] === 'function') {\n logger.info('request options not provided, deriving from the url', url)\n return urlToHttpOptions(url)\n }\n\n if (args[1]) {\n logger.info('has custom RequestOptions!', args[1])\n const requestOptionsFromUrl = urlToHttpOptions(url)\n\n logger.info('derived RequestOptions from the URL:', requestOptionsFromUrl)\n\n /**\n * Clone the request options to lock their state\n * at the moment they are provided to `ClientRequest`.\n * @see https://github.com/mswjs/interceptors/issues/86\n */\n logger.info('cloning RequestOptions...')\n const clonedRequestOptions = cloneObject(args[1])\n logger.info('successfully cloned RequestOptions!', clonedRequestOptions)\n\n return {\n ...requestOptionsFromUrl,\n ...clonedRequestOptions,\n }\n }\n\n logger.info('using an empty object as request options')\n return {} as RequestOptions\n}\n\n/**\n * Overrides the given `URL` instance with the explicit properties provided\n * on the `RequestOptions` object. The options object takes precedence,\n * and will replace URL properties like \"host\", \"path\", and \"port\", if specified.\n */\nfunction overrideUrlByRequestOptions(url: URL, options: RequestOptions): URL {\n url.host = options.host || url.host\n url.hostname = options.hostname || url.hostname\n url.port = options.port ? options.port.toString() : url.port\n\n if (options.path) {\n const parsedOptionsPath = parseUrl(options.path, false)\n url.pathname = parsedOptionsPath.pathname || ''\n url.search = parsedOptionsPath.search || ''\n }\n\n return url\n}\n\nfunction resolveCallback(\n args: ClientRequestArgs\n): HttpRequestCallback | undefined {\n return typeof args[1] === 'function' ? args[1] : args[2]\n}\n\nexport type NormalizedClientRequestArgs = [\n url: URL,\n options: ResolvedRequestOptions,\n callback?: HttpRequestCallback\n]\n\n/**\n * Normalizes parameters given to a `http.request` call\n * so it always has a `URL` and `RequestOptions`.\n */\nexport function normalizeClientRequestArgs(\n defaultProtocol: string,\n args: ClientRequestArgs\n): NormalizedClientRequestArgs {\n let url: URL\n let options: ResolvedRequestOptions\n let callback: HttpRequestCallback | undefined\n\n logger.info('arguments', args)\n logger.info('using default protocol:', defaultProtocol)\n\n // Support \"http.request()\" calls without any arguments.\n // That call results in a \"GET http://localhost\" request.\n if (args.length === 0) {\n const url = new URL('http://localhost')\n const options = resolveRequestOptions(args, url)\n return [url, options]\n }\n\n // Convert a url string into a URL instance\n // and derive request options from it.\n if (typeof args[0] === 'string') {\n logger.info('first argument is a location string:', args[0])\n\n url = new URL(args[0])\n logger.info('created a url:', url)\n\n const requestOptionsFromUrl = urlToHttpOptions(url)\n logger.info('request options from url:', requestOptionsFromUrl)\n\n options = resolveRequestOptions(args, url)\n logger.info('resolved request options:', options)\n\n callback = resolveCallback(args)\n }\n // Handle a given URL instance as-is\n // and derive request options from it.\n else if (args[0] instanceof URL) {\n url = args[0]\n logger.info('first argument is a URL:', url)\n\n // Check if the second provided argument is RequestOptions.\n // If it is, check if \"options.path\" was set and rewrite it\n // on the input URL.\n // Do this before resolving options from the URL below\n // to prevent query string from being duplicated in the path.\n if (typeof args[1] !== 'undefined' && isObject(args[1])) {\n url = overrideUrlByRequestOptions(url, args[1])\n }\n\n options = resolveRequestOptions(args, url)\n logger.info('derived request options:', options)\n\n callback = resolveCallback(args)\n }\n // Handle a legacy URL instance and re-normalize from either a RequestOptions object\n // or a WHATWG URL.\n else if ('hash' in args[0] && !('method' in args[0])) {\n const [legacyUrl] = args\n logger.info('first argument is a legacy URL:', legacyUrl)\n\n if (legacyUrl.hostname === null) {\n /**\n * We are dealing with a relative url, so use the path as an \"option\" and\n * merge in any existing options, giving priority to exising options -- i.e. a path in any\n * existing options will take precedence over the one contained in the url. This is consistent\n * with the behaviour in ClientRequest.\n * @see https://github.com/nodejs/node/blob/d84f1312915fe45fe0febe888db692c74894c382/lib/_http_client.js#L122\n */\n logger.info('given legacy URL is relative (no hostname)')\n\n return isObject(args[1])\n ? normalizeClientRequestArgs(defaultProtocol, [\n { path: legacyUrl.path, ...args[1] },\n args[2],\n ])\n : normalizeClientRequestArgs(defaultProtocol, [\n { path: legacyUrl.path },\n args[1] as HttpRequestCallback,\n ])\n }\n\n logger.info('given legacy url is absolute')\n\n // We are dealing with an absolute URL, so convert to WHATWG and try again.\n const resolvedUrl = new URL(legacyUrl.href)\n\n return args[1] === undefined\n ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl])\n : typeof args[1] === 'function'\n ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl, args[1]])\n : normalizeClientRequestArgs(defaultProtocol, [\n resolvedUrl,\n args[1],\n args[2],\n ])\n }\n // Handle a given \"RequestOptions\" object as-is\n // and derive the URL instance from it.\n else if (isObject(args[0])) {\n options = { ...(args[0] as any) }\n logger.info('first argument is RequestOptions:', options)\n\n // When handling a \"RequestOptions\" object without an explicit \"protocol\",\n // infer the protocol from the request issuing module (http/https).\n options.protocol = options.protocol || defaultProtocol\n logger.info('normalized request options:', options)\n\n url = getUrlByRequestOptions(options)\n logger.info('created a URL from RequestOptions:', url.href)\n\n callback = resolveCallback(args)\n } else {\n throw new Error(\n `Failed to construct ClientRequest with these parameters: ${args}`\n )\n }\n\n options.protocol = options.protocol || url.protocol\n options.method = options.method || 'GET'\n\n /**\n * Infer a fallback agent from the URL protocol.\n * The interception is done on the \"ClientRequest\" level (\"NodeClientRequest\")\n * and it may miss the correct agent. Always align the agent\n * with the URL protocol, if not provided.\n *\n * @note Respect the \"agent: false\" value.\n */\n if (typeof options.agent === 'undefined') {\n const agent =\n options.protocol === 'https:'\n ? new HttpsAgent({\n rejectUnauthorized: options.rejectUnauthorized,\n })\n : new HttpAgent()\n\n options.agent = agent\n logger.info('resolved fallback agent:', agent)\n }\n\n /**\n * Ensure that the default Agent is always set.\n * This prevents the protocol mismatch for requests with { agent: false },\n * where the global Agent is inferred.\n * @see https://github.com/mswjs/msw/issues/1150\n * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L130\n * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L157-L159\n */\n if (!options._defaultAgent) {\n logger.info(\n 'has no default agent, setting the default agent for \"%s\"',\n options.protocol\n )\n\n options._defaultAgent =\n options.protocol === 'https:' ? httpsGlobalAgent : httpGlobalAgent\n }\n\n logger.info('successfully resolved url:', url.href)\n logger.info('successfully resolved options:', options)\n logger.info('successfully resolved callback:', callback)\n\n /**\n * @note If the user-provided URL is not a valid URL in Node.js,\n * (e.g. the one provided by the JSDOM polyfills), case it to\n * string. Otherwise, this throws on Node.js incompatibility\n * (`ERR_INVALID_ARG_TYPE` on the connection listener)\n * @see https://github.com/node-fetch/node-fetch/issues/1376#issuecomment-966435555\n */\n if (!(url instanceof URL)) {\n url = (url as any).toString()\n }\n\n return [url, options, callback]\n}\n","import { Agent } from 'http'\nimport { RequestOptions, Agent as HttpsAgent } from 'https'\nimport { Logger } from '@open-draft/logger'\n\nconst logger = new Logger('utils getUrlByRequestOptions')\n\n// Request instance constructed by the \"request\" library\n// has a \"self\" property that has a \"uri\" field. This is\n// reproducible by performing a \"XMLHttpRequest\" request in JSDOM.\nexport interface RequestSelf {\n uri?: URL\n}\n\nexport type ResolvedRequestOptions = RequestOptions & RequestSelf\n\nexport const DEFAULT_PATH = '/'\nconst DEFAULT_PROTOCOL = 'http:'\nconst DEFAULT_HOSTNAME = 'localhost'\nconst SSL_PORT = 443\n\nfunction getAgent(\n options: ResolvedRequestOptions\n): Agent | HttpsAgent | undefined {\n return options.agent instanceof Agent ? options.agent : undefined\n}\n\nfunction getProtocolByRequestOptions(options: ResolvedRequestOptions): string {\n if (options.protocol) {\n return options.protocol\n }\n\n const agent = getAgent(options)\n const agentProtocol = (agent as RequestOptions)?.protocol\n\n if (agentProtocol) {\n return agentProtocol\n }\n\n const port = getPortByRequestOptions(options)\n const isSecureRequest = options.cert || port === SSL_PORT\n\n return isSecureRequest ? 'https:' : options.uri?.protocol || DEFAULT_PROTOCOL\n}\n\nfunction getPortByRequestOptions(\n options: ResolvedRequestOptions\n): number | undefined {\n // Use the explicitly provided port.\n if (options.port) {\n return Number(options.port)\n }\n\n // Otherwise, try to resolve port from the agent.\n const agent = getAgent(options)\n\n if ((agent as HttpsAgent)?.options.port) {\n return Number((agent as HttpsAgent).options.port)\n }\n\n if ((agent as RequestOptions)?.defaultPort) {\n return Number((agent as RequestOptions).defaultPort)\n }\n\n // Lastly, return undefined indicating that the port\n // must inferred from the protocol. Do not infer it here.\n return undefined\n}\n\ninterface RequestAuth {\n username: string\n password: string\n}\n\nfunction getAuthByRequestOptions(\n options: ResolvedRequestOptions\n): RequestAuth | undefined {\n if (options.auth) {\n const [username, password] = options.auth.split(':')\n return { username, password }\n }\n}\n\n/**\n * Returns true if host looks like an IPv6 address without surrounding brackets\n * It assumes any host containing `:` is definitely not IPv4 and probably IPv6,\n * but note that this could include invalid IPv6 addresses as well.\n */\nfunction isRawIPv6Address(host: string): boolean {\n return host.includes(':') && !host.startsWith('[') && !host.endsWith(']')\n}\n\nfunction getHostname(options: ResolvedRequestOptions): string | undefined {\n let host = options.hostname || options.host\n\n if (host) {\n if (isRawIPv6Address(host)) {\n host = `[${host}]`\n }\n\n // Check the presence of the port, and if it's present,\n // remove it from the host, returning a hostname.\n return new URL(`http://${host}`).hostname\n }\n\n return DEFAULT_HOSTNAME\n}\n\n/**\n * Creates a `URL` instance from a given `RequestOptions` object.\n */\nexport function getUrlByRequestOptions(options: ResolvedRequestOptions): URL {\n logger.info('request options', options)\n\n if (options.uri) {\n logger.info(\n 'constructing url from explicitly provided \"options.uri\": %s',\n options.uri\n )\n return new URL(options.uri.href)\n }\n\n logger.info('figuring out url from request options...')\n\n const protocol = getProtocolByRequestOptions(options)\n logger.info('protocol', protocol)\n\n const port = getPortByRequestOptions(options)\n logger.info('port', port)\n\n const hostname = getHostname(options)\n logger.info('hostname', hostname)\n\n const path = options.path || DEFAULT_PATH\n logger.info('path', path)\n\n const credentials = getAuthByRequestOptions(options)\n logger.info('credentials', credentials)\n\n const authString = credentials\n ? `${credentials.username}:${credentials.password}@`\n : ''\n logger.info('auth string:', authString)\n\n const portString = typeof port !== 'undefined' ? `:${port}` : ''\n const url = new URL(`${protocol}//${hostname}${portString}${path}`)\n url.username = credentials?.username || ''\n url.password = credentials?.password || ''\n\n logger.info('created url:', url)\n\n return url\n}\n","import { Logger } from '@open-draft/logger'\n\nconst logger = new Logger('cloneObject')\n\nfunction isPlainObject(obj?: Record): boolean {\n logger.info('is plain object?', obj)\n\n if (obj == null || !obj.constructor?.name) {\n logger.info('given object is undefined, not a plain object...')\n return false\n }\n\n logger.info('checking the object constructor:', obj.constructor.name)\n return obj.constructor.name === 'Object'\n}\n\nexport function cloneObject>(\n obj: ObjectType\n): ObjectType {\n logger.info('cloning object:', obj)\n\n const enumerableProperties = Object.entries(obj).reduce>(\n (acc, [key, value]) => {\n logger.info('analyzing key-value pair:', key, value)\n\n // Recursively clone only plain objects, omitting class instances.\n acc[key] = isPlainObject(value) ? cloneObject(value) : value\n return acc\n },\n {}\n )\n\n return isPlainObject(obj)\n ? enumerableProperties\n : Object.assign(Object.getPrototypeOf(obj), enumerableProperties)\n}\n","/**\n * Determines if a given value is an instance of object.\n */\nexport function isObject(value: any, loose = false): value is T {\n return loose\n ? Object.prototype.toString.call(value).startsWith('[object ')\n : Object.prototype.toString.call(value) === '[object Object]'\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-5KMS5CTP.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-5KMS5CTP.mjs new file mode 100644 index 0000000000..12e6e12bde --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-5KMS5CTP.mjs @@ -0,0 +1,230 @@ +// src/RequestController.ts +import { invariant } from "outvariant"; +import { DeferredPromise } from "@open-draft/deferred-promise"; + +// src/InterceptorError.ts +var InterceptorError = class extends Error { + constructor(message) { + super(message); + this.name = "InterceptorError"; + Object.setPrototypeOf(this, InterceptorError.prototype); + } +}; + +// src/RequestController.ts +var kRequestHandled = Symbol("kRequestHandled"); +var kResponsePromise = Symbol("kResponsePromise"); +var RequestController = class { + constructor(request) { + this.request = request; + this[kRequestHandled] = false; + this[kResponsePromise] = new DeferredPromise(); + } + /** + * Respond to this request with the given `Response` instance. + * @example + * controller.respondWith(new Response()) + * controller.respondWith(Response.json({ id })) + * controller.respondWith(Response.error()) + */ + respondWith(response) { + invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to respond to the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(response); + } + /** + * Error this request with the given error. + * @example + * controller.errorWith() + * controller.errorWith(new Error('Oops!')) + */ + errorWith(error) { + invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to error the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(error); + } +}; +kResponsePromise, kRequestHandled; + +// src/utils/emitAsync.ts +async function emitAsync(emitter, eventName, ...data) { + const listners = emitter.listeners(eventName); + if (listners.length === 0) { + return; + } + for (const listener of listners) { + await listener.apply(emitter, data); + } +} + +// src/utils/handleRequest.ts +import { DeferredPromise as DeferredPromise2 } from "@open-draft/deferred-promise"; +import { until } from "@open-draft/until"; + +// src/utils/isPropertyAccessible.ts +function isPropertyAccessible(obj, key) { + try { + obj[key]; + return true; + } catch (e) { + return false; + } +} + +// src/utils/responseUtils.ts +function createServerErrorResponse(body) { + return new Response( + JSON.stringify( + body instanceof Error ? { + name: body.name, + message: body.message, + stack: body.stack + } : body + ), + { + status: 500, + statusText: "Unhandled Exception", + headers: { + "Content-Type": "application/json" + } + } + ); +} +function isResponseError(response) { + return isPropertyAccessible(response, "type") && response.type === "error"; +} + +// src/utils/isNodeLikeError.ts +function isNodeLikeError(error) { + if (error == null) { + return false; + } + if (!(error instanceof Error)) { + return false; + } + return "code" in error && "errno" in error; +} + +// src/utils/handleRequest.ts +async function handleRequest(options) { + const handleResponse = async (response) => { + if (response instanceof Error) { + options.onError(response); + } else if (isResponseError(response)) { + options.onRequestError(response); + } else { + await options.onResponse(response); + } + return true; + }; + const handleResponseError = async (error) => { + if (error instanceof InterceptorError) { + throw result.error; + } + if (isNodeLikeError(error)) { + options.onError(error); + return true; + } + if (error instanceof Response) { + return await handleResponse(error); + } + return false; + }; + options.emitter.once("request", ({ requestId: pendingRequestId }) => { + if (pendingRequestId !== options.requestId) { + return; + } + if (options.controller[kResponsePromise].state === "pending") { + options.controller[kResponsePromise].resolve(void 0); + } + }); + const requestAbortPromise = new DeferredPromise2(); + if (options.request.signal) { + if (options.request.signal.aborted) { + requestAbortPromise.reject(options.request.signal.reason); + } else { + options.request.signal.addEventListener( + "abort", + () => { + requestAbortPromise.reject(options.request.signal.reason); + }, + { once: true } + ); + } + } + const result = await until(async () => { + const requestListtenersPromise = emitAsync(options.emitter, "request", { + requestId: options.requestId, + request: options.request, + controller: options.controller + }); + await Promise.race([ + // Short-circuit the request handling promise if the request gets aborted. + requestAbortPromise, + requestListtenersPromise, + options.controller[kResponsePromise] + ]); + const mockedResponse = await options.controller[kResponsePromise]; + return mockedResponse; + }); + if (requestAbortPromise.state === "rejected") { + options.onError(requestAbortPromise.rejectionReason); + return true; + } + if (result.error) { + if (await handleResponseError(result.error)) { + return true; + } + if (options.emitter.listenerCount("unhandledException") > 0) { + const unhandledExceptionController = new RequestController( + options.request + ); + await emitAsync(options.emitter, "unhandledException", { + error: result.error, + request: options.request, + requestId: options.requestId, + controller: unhandledExceptionController + }).then(() => { + if (unhandledExceptionController[kResponsePromise].state === "pending") { + unhandledExceptionController[kResponsePromise].resolve(void 0); + } + }); + const nextResult = await until( + () => unhandledExceptionController[kResponsePromise] + ); + if (nextResult.error) { + return handleResponseError(nextResult.error); + } + if (nextResult.data) { + return handleResponse(nextResult.data); + } + } + options.onResponse(createServerErrorResponse(result.error)); + return true; + } + if (result.data) { + return handleResponse(result.data); + } + return false; +} + +export { + isPropertyAccessible, + createServerErrorResponse, + RequestController, + emitAsync, + handleRequest +}; +//# sourceMappingURL=chunk-5KMS5CTP.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-5KMS5CTP.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-5KMS5CTP.mjs.map new file mode 100644 index 0000000000..41215da760 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-5KMS5CTP.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/RequestController.ts","../../src/InterceptorError.ts","../../src/utils/emitAsync.ts","../../src/utils/handleRequest.ts","../../src/utils/isPropertyAccessible.ts","../../src/utils/responseUtils.ts","../../src/utils/isNodeLikeError.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { InterceptorError } from './InterceptorError'\n\nconst kRequestHandled = Symbol('kRequestHandled')\nexport const kResponsePromise = Symbol('kResponsePromise')\n\nexport class RequestController {\n /**\n * Internal response promise.\n * Available only for the library internals to grab the\n * response instance provided by the developer.\n * @note This promise cannot be rejected. It's either infinitely\n * pending or resolved with whichever Response was passed to `respondWith()`.\n */\n [kResponsePromise]: DeferredPromise;\n\n /**\n * Internal flag indicating if this request has been handled.\n * @note The response promise becomes \"fulfilled\" on the next tick.\n */\n [kRequestHandled]: boolean\n\n constructor(private request: Request) {\n this[kRequestHandled] = false\n this[kResponsePromise] = new DeferredPromise()\n }\n\n /**\n * Respond to this request with the given `Response` instance.\n * @example\n * controller.respondWith(new Response())\n * controller.respondWith(Response.json({ id }))\n * controller.respondWith(Response.error())\n */\n public respondWith(response: Response): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to respond to the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n this[kResponsePromise].resolve(response)\n\n /**\n * @note The request conrtoller doesn't do anything\n * apart from letting the interceptor await the response\n * provided by the developer through the response promise.\n * Each interceptor implements the actual respondWith/errorWith\n * logic based on that interceptor's needs.\n */\n }\n\n /**\n * Error this request with the given error.\n * @example\n * controller.errorWith()\n * controller.errorWith(new Error('Oops!'))\n */\n public errorWith(error?: Error): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to error the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n\n /**\n * @note Resolve the response promise, not reject.\n * This helps us differentiate between unhandled exceptions\n * and intended errors (\"errorWith\") while waiting for the response.\n */\n this[kResponsePromise].resolve(error)\n }\n}\n","export class InterceptorError extends Error {\n constructor(message?: string) {\n super(message)\n this.name = 'InterceptorError'\n Object.setPrototypeOf(this, InterceptorError.prototype)\n }\n}\n","import { Emitter, EventMap } from 'strict-event-emitter'\n\n/**\n * Emits an event on the given emitter but executes\n * the listeners sequentially. This accounts for asynchronous\n * listeners (e.g. those having \"sleep\" and handling the request).\n */\nexport async function emitAsync<\n Events extends EventMap,\n EventName extends keyof Events\n>(\n emitter: Emitter,\n eventName: EventName,\n ...data: Events[EventName]\n): Promise {\n const listners = emitter.listeners(eventName)\n\n if (listners.length === 0) {\n return\n }\n\n for (const listener of listners) {\n await listener.apply(emitter, data)\n }\n}\n","import type { Emitter } from 'strict-event-emitter'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport type { HttpRequestEventMap } from '../glossary'\nimport { emitAsync } from './emitAsync'\nimport { kResponsePromise, RequestController } from '../RequestController'\nimport {\n createServerErrorResponse,\n isResponseError,\n ResponseError,\n} from './responseUtils'\nimport { InterceptorError } from '../InterceptorError'\nimport { isNodeLikeError } from './isNodeLikeError'\n\ninterface HandleRequestOptions {\n requestId: string\n request: Request\n emitter: Emitter\n controller: RequestController\n\n /**\n * Called when the request has been handled\n * with the given `Response` instance.\n */\n onResponse: (response: Response) => void | Promise\n\n /**\n * Called when the request has been handled\n * with the given `Response.error()` instance.\n */\n onRequestError: (response: ResponseError) => void\n\n /**\n * Called when an unhandled error happens during the\n * request handling. This is never a thrown error/response.\n */\n onError: (error: unknown) => void\n}\n\n/**\n * @returns {Promise} Indicates whether the request has been handled.\n */\nexport async function handleRequest(\n options: HandleRequestOptions\n): Promise {\n const handleResponse = async (response: Response | Error) => {\n if (response instanceof Error) {\n options.onError(response)\n }\n\n // Handle \"Response.error()\" instances.\n else if (isResponseError(response)) {\n options.onRequestError(response)\n } else {\n await options.onResponse(response)\n }\n\n return true\n }\n\n const handleResponseError = async (error: unknown): Promise => {\n // Forward the special interceptor error instances\n // to the developer. These must not be handled in any way.\n if (error instanceof InterceptorError) {\n throw result.error\n }\n\n // Support mocking Node.js-like errors.\n if (isNodeLikeError(error)) {\n options.onError(error)\n return true\n }\n\n // Handle thrown responses.\n if (error instanceof Response) {\n return await handleResponse(error)\n }\n\n return false\n }\n\n // Add the last \"request\" listener to check if the request\n // has been handled in any way. If it hasn't, resolve the\n // response promise with undefined.\n options.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== options.requestId) {\n return\n }\n\n if (options.controller[kResponsePromise].state === 'pending') {\n options.controller[kResponsePromise].resolve(undefined)\n }\n })\n\n const requestAbortPromise = new DeferredPromise()\n\n /**\n * @note `signal` is not always defined in React Native.\n */\n if (options.request.signal) {\n if (options.request.signal.aborted) {\n requestAbortPromise.reject(options.request.signal.reason)\n } else {\n options.request.signal.addEventListener(\n 'abort',\n () => {\n requestAbortPromise.reject(options.request.signal.reason)\n },\n { once: true }\n )\n }\n }\n\n const result = await until(async () => {\n // Emit the \"request\" event and wait until all the listeners\n // for that event are finished (e.g. async listeners awaited).\n // By the end of this promise, the developer cannot affect the\n // request anymore.\n const requestListtenersPromise = emitAsync(options.emitter, 'request', {\n requestId: options.requestId,\n request: options.request,\n controller: options.controller,\n })\n\n await Promise.race([\n // Short-circuit the request handling promise if the request gets aborted.\n requestAbortPromise,\n requestListtenersPromise,\n options.controller[kResponsePromise],\n ])\n\n // The response promise will settle immediately once\n // the developer calls either \"respondWith\" or \"errorWith\".\n const mockedResponse = await options.controller[kResponsePromise]\n return mockedResponse\n })\n\n // Handle the request being aborted while waiting for the request listeners.\n if (requestAbortPromise.state === 'rejected') {\n options.onError(requestAbortPromise.rejectionReason)\n return true\n }\n\n if (result.error) {\n // Handle the error during the request listener execution.\n // These can be thrown responses or request errors.\n if (await handleResponseError(result.error)) {\n return true\n }\n\n // If the developer has added \"unhandledException\" listeners,\n // allow them to handle the error. They can translate it to a\n // mocked response, network error, or forward it as-is.\n if (options.emitter.listenerCount('unhandledException') > 0) {\n // Create a new request controller just for the unhandled exception case.\n // This is needed because the original controller might have been already\n // interacted with (e.g. \"respondWith\" or \"errorWith\" called on it).\n const unhandledExceptionController = new RequestController(\n options.request\n )\n\n await emitAsync(options.emitter, 'unhandledException', {\n error: result.error,\n request: options.request,\n requestId: options.requestId,\n controller: unhandledExceptionController,\n }).then(() => {\n // If all the \"unhandledException\" listeners have finished\n // but have not handled the response in any way, preemptively\n // resolve the pending response promise from the new controller.\n // This prevents it from hanging forever.\n if (\n unhandledExceptionController[kResponsePromise].state === 'pending'\n ) {\n unhandledExceptionController[kResponsePromise].resolve(undefined)\n }\n })\n\n const nextResult = await until(\n () => unhandledExceptionController[kResponsePromise]\n )\n\n /**\n * @note Handle the result of the unhandled controller\n * in the same way as the original request controller.\n * The exception here is that thrown errors within the\n * \"unhandledException\" event do NOT result in another\n * emit of the same event. They are forwarded as-is.\n */\n if (nextResult.error) {\n return handleResponseError(nextResult.error)\n }\n\n if (nextResult.data) {\n return handleResponse(nextResult.data)\n }\n }\n\n // Otherwise, coerce unhandled exceptions to a 500 Internal Server Error response.\n options.onResponse(createServerErrorResponse(result.error))\n return true\n }\n\n /**\n * Handle a mocked Response instance.\n * @note That this can also be an Error in case\n * the developer called \"errorWith\". This differentiates\n * unhandled exceptions from intended errors.\n */\n if (result.data) {\n return handleResponse(result.data)\n }\n\n // In all other cases, consider the request unhandled.\n // The interceptor must perform it as-is.\n return false\n}\n","/**\n * A function that validates if property access is possible on an object\n * without throwing. It returns `true` if the property access is possible\n * and `false` otherwise.\n *\n * Environments like miniflare will throw on property access on certain objects\n * like Request and Response, for unimplemented properties.\n */\nexport function isPropertyAccessible>(\n obj: Obj,\n key: keyof Obj\n) {\n try {\n obj[key]\n return true\n } catch {\n return false\n }\n}\n","import { isPropertyAccessible } from './isPropertyAccessible'\n\n/**\n * Creates a generic 500 Unhandled Exception response.\n */\nexport function createServerErrorResponse(body: unknown): Response {\n return new Response(\n JSON.stringify(\n body instanceof Error\n ? {\n name: body.name,\n message: body.message,\n stack: body.stack,\n }\n : body\n ),\n {\n status: 500,\n statusText: 'Unhandled Exception',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n}\n\nexport type ResponseError = Response & { type: 'error' }\n\n/**\n * Check if the given response is a `Response.error()`.\n *\n * @note Some environments, like Miniflare (Cloudflare) do not\n * implement the \"Response.type\" property and throw on its access.\n * Safely check if we can access \"type\" on \"Response\" before continuing.\n * @see https://github.com/mswjs/msw/issues/1834\n */\nexport function isResponseError(response: Response): response is ResponseError {\n return isPropertyAccessible(response, 'type') && response.type === 'error'\n}\n","export function isNodeLikeError(\n error: unknown\n): error is NodeJS.ErrnoException {\n if (error == null) {\n return false\n }\n\n if (!(error instanceof Error)) {\n return false\n }\n\n return 'code' in error && 'errno' in error\n}\n"],"mappings":"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","names":["DeferredPromise","DeferredPromise"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-6HYIRFX2.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-6HYIRFX2.mjs new file mode 100644 index 0000000000..05b6c33cb2 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-6HYIRFX2.mjs @@ -0,0 +1,22 @@ +// src/utils/bufferUtils.ts +var encoder = new TextEncoder(); +function encodeBuffer(text) { + return encoder.encode(text); +} +function decodeBuffer(buffer, encoding) { + const decoder = new TextDecoder(encoding); + return decoder.decode(buffer); +} +function toArrayBuffer(array) { + return array.buffer.slice( + array.byteOffset, + array.byteOffset + array.byteLength + ); +} + +export { + encodeBuffer, + decodeBuffer, + toArrayBuffer +}; +//# sourceMappingURL=chunk-6HYIRFX2.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-6HYIRFX2.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-6HYIRFX2.mjs.map new file mode 100644 index 0000000000..6f27915c41 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-6HYIRFX2.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/bufferUtils.ts"],"sourcesContent":["const encoder = new TextEncoder()\n\nexport function encodeBuffer(text: string): Uint8Array {\n return encoder.encode(text)\n}\n\nexport function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string {\n const decoder = new TextDecoder(encoding)\n return decoder.decode(buffer)\n}\n\n/**\n * Create an `ArrayBuffer` from the given `Uint8Array`.\n * Takes the byte offset into account to produce the right buffer\n * in the case when the buffer is bigger than the data view.\n */\nexport function toArrayBuffer(array: Uint8Array): ArrayBuffer {\n return array.buffer.slice(\n array.byteOffset,\n array.byteOffset + array.byteLength\n )\n}\n"],"mappings":";AAAA,IAAM,UAAU,IAAI,YAAY;AAEzB,SAAS,aAAa,MAA0B;AACrD,SAAO,QAAQ,OAAO,IAAI;AAC5B;AAEO,SAAS,aAAa,QAAqB,UAA2B;AAC3E,QAAM,UAAU,IAAI,YAAY,QAAQ;AACxC,SAAO,QAAQ,OAAO,MAAM;AAC9B;AAOO,SAAS,cAAc,OAAgC;AAC5D,SAAO,MAAM,OAAO;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,aAAa,MAAM;AAAA,EAC3B;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-6L3PFBGT.js b/node_modules/@mswjs/interceptors/lib/node/chunk-6L3PFBGT.js new file mode 100644 index 0000000000..4dc5e0cb77 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-6L3PFBGT.js @@ -0,0 +1,230 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/RequestController.ts +var _outvariant = require('outvariant'); +var _deferredpromise = require('@open-draft/deferred-promise'); + +// src/InterceptorError.ts +var InterceptorError = class extends Error { + constructor(message) { + super(message); + this.name = "InterceptorError"; + Object.setPrototypeOf(this, InterceptorError.prototype); + } +}; + +// src/RequestController.ts +var kRequestHandled = Symbol("kRequestHandled"); +var kResponsePromise = Symbol("kResponsePromise"); +var RequestController = class { + constructor(request) { + this.request = request; + this[kRequestHandled] = false; + this[kResponsePromise] = new (0, _deferredpromise.DeferredPromise)(); + } + /** + * Respond to this request with the given `Response` instance. + * @example + * controller.respondWith(new Response()) + * controller.respondWith(Response.json({ id })) + * controller.respondWith(Response.error()) + */ + respondWith(response) { + _outvariant.invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to respond to the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(response); + } + /** + * Error this request with the given error. + * @example + * controller.errorWith() + * controller.errorWith(new Error('Oops!')) + */ + errorWith(error) { + _outvariant.invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to error the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ); + this[kRequestHandled] = true; + this[kResponsePromise].resolve(error); + } +}; +kResponsePromise, kRequestHandled; + +// src/utils/emitAsync.ts +async function emitAsync(emitter, eventName, ...data) { + const listners = emitter.listeners(eventName); + if (listners.length === 0) { + return; + } + for (const listener of listners) { + await listener.apply(emitter, data); + } +} + +// src/utils/handleRequest.ts + +var _until = require('@open-draft/until'); + +// src/utils/isPropertyAccessible.ts +function isPropertyAccessible(obj, key) { + try { + obj[key]; + return true; + } catch (e) { + return false; + } +} + +// src/utils/responseUtils.ts +function createServerErrorResponse(body) { + return new Response( + JSON.stringify( + body instanceof Error ? { + name: body.name, + message: body.message, + stack: body.stack + } : body + ), + { + status: 500, + statusText: "Unhandled Exception", + headers: { + "Content-Type": "application/json" + } + } + ); +} +function isResponseError(response) { + return isPropertyAccessible(response, "type") && response.type === "error"; +} + +// src/utils/isNodeLikeError.ts +function isNodeLikeError(error) { + if (error == null) { + return false; + } + if (!(error instanceof Error)) { + return false; + } + return "code" in error && "errno" in error; +} + +// src/utils/handleRequest.ts +async function handleRequest(options) { + const handleResponse = async (response) => { + if (response instanceof Error) { + options.onError(response); + } else if (isResponseError(response)) { + options.onRequestError(response); + } else { + await options.onResponse(response); + } + return true; + }; + const handleResponseError = async (error) => { + if (error instanceof InterceptorError) { + throw result.error; + } + if (isNodeLikeError(error)) { + options.onError(error); + return true; + } + if (error instanceof Response) { + return await handleResponse(error); + } + return false; + }; + options.emitter.once("request", ({ requestId: pendingRequestId }) => { + if (pendingRequestId !== options.requestId) { + return; + } + if (options.controller[kResponsePromise].state === "pending") { + options.controller[kResponsePromise].resolve(void 0); + } + }); + const requestAbortPromise = new (0, _deferredpromise.DeferredPromise)(); + if (options.request.signal) { + if (options.request.signal.aborted) { + requestAbortPromise.reject(options.request.signal.reason); + } else { + options.request.signal.addEventListener( + "abort", + () => { + requestAbortPromise.reject(options.request.signal.reason); + }, + { once: true } + ); + } + } + const result = await _until.until.call(void 0, async () => { + const requestListtenersPromise = emitAsync(options.emitter, "request", { + requestId: options.requestId, + request: options.request, + controller: options.controller + }); + await Promise.race([ + // Short-circuit the request handling promise if the request gets aborted. + requestAbortPromise, + requestListtenersPromise, + options.controller[kResponsePromise] + ]); + const mockedResponse = await options.controller[kResponsePromise]; + return mockedResponse; + }); + if (requestAbortPromise.state === "rejected") { + options.onError(requestAbortPromise.rejectionReason); + return true; + } + if (result.error) { + if (await handleResponseError(result.error)) { + return true; + } + if (options.emitter.listenerCount("unhandledException") > 0) { + const unhandledExceptionController = new RequestController( + options.request + ); + await emitAsync(options.emitter, "unhandledException", { + error: result.error, + request: options.request, + requestId: options.requestId, + controller: unhandledExceptionController + }).then(() => { + if (unhandledExceptionController[kResponsePromise].state === "pending") { + unhandledExceptionController[kResponsePromise].resolve(void 0); + } + }); + const nextResult = await _until.until.call(void 0, + () => unhandledExceptionController[kResponsePromise] + ); + if (nextResult.error) { + return handleResponseError(nextResult.error); + } + if (nextResult.data) { + return handleResponse(nextResult.data); + } + } + options.onResponse(createServerErrorResponse(result.error)); + return true; + } + if (result.data) { + return handleResponse(result.data); + } + return false; +} + + + + + + + +exports.isPropertyAccessible = isPropertyAccessible; exports.createServerErrorResponse = createServerErrorResponse; exports.RequestController = RequestController; exports.emitAsync = emitAsync; exports.handleRequest = handleRequest; +//# sourceMappingURL=chunk-6L3PFBGT.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-6L3PFBGT.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-6L3PFBGT.js.map new file mode 100644 index 0000000000..9c5a436574 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-6L3PFBGT.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/RequestController.ts","../../src/InterceptorError.ts","../../src/utils/emitAsync.ts","../../src/utils/handleRequest.ts","../../src/utils/isPropertyAccessible.ts","../../src/utils/responseUtils.ts","../../src/utils/isNodeLikeError.ts"],"names":["DeferredPromise"],"mappings":"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","sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { InterceptorError } from './InterceptorError'\n\nconst kRequestHandled = Symbol('kRequestHandled')\nexport const kResponsePromise = Symbol('kResponsePromise')\n\nexport class RequestController {\n /**\n * Internal response promise.\n * Available only for the library internals to grab the\n * response instance provided by the developer.\n * @note This promise cannot be rejected. It's either infinitely\n * pending or resolved with whichever Response was passed to `respondWith()`.\n */\n [kResponsePromise]: DeferredPromise;\n\n /**\n * Internal flag indicating if this request has been handled.\n * @note The response promise becomes \"fulfilled\" on the next tick.\n */\n [kRequestHandled]: boolean\n\n constructor(private request: Request) {\n this[kRequestHandled] = false\n this[kResponsePromise] = new DeferredPromise()\n }\n\n /**\n * Respond to this request with the given `Response` instance.\n * @example\n * controller.respondWith(new Response())\n * controller.respondWith(Response.json({ id }))\n * controller.respondWith(Response.error())\n */\n public respondWith(response: Response): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to respond to the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n this[kResponsePromise].resolve(response)\n\n /**\n * @note The request conrtoller doesn't do anything\n * apart from letting the interceptor await the response\n * provided by the developer through the response promise.\n * Each interceptor implements the actual respondWith/errorWith\n * logic based on that interceptor's needs.\n */\n }\n\n /**\n * Error this request with the given error.\n * @example\n * controller.errorWith()\n * controller.errorWith(new Error('Oops!'))\n */\n public errorWith(error?: Error): void {\n invariant.as(\n InterceptorError,\n !this[kRequestHandled],\n 'Failed to error the \"%s %s\" request: the \"request\" event has already been handled.',\n this.request.method,\n this.request.url\n )\n\n this[kRequestHandled] = true\n\n /**\n * @note Resolve the response promise, not reject.\n * This helps us differentiate between unhandled exceptions\n * and intended errors (\"errorWith\") while waiting for the response.\n */\n this[kResponsePromise].resolve(error)\n }\n}\n","export class InterceptorError extends Error {\n constructor(message?: string) {\n super(message)\n this.name = 'InterceptorError'\n Object.setPrototypeOf(this, InterceptorError.prototype)\n }\n}\n","import { Emitter, EventMap } from 'strict-event-emitter'\n\n/**\n * Emits an event on the given emitter but executes\n * the listeners sequentially. This accounts for asynchronous\n * listeners (e.g. those having \"sleep\" and handling the request).\n */\nexport async function emitAsync<\n Events extends EventMap,\n EventName extends keyof Events\n>(\n emitter: Emitter,\n eventName: EventName,\n ...data: Events[EventName]\n): Promise {\n const listners = emitter.listeners(eventName)\n\n if (listners.length === 0) {\n return\n }\n\n for (const listener of listners) {\n await listener.apply(emitter, data)\n }\n}\n","import type { Emitter } from 'strict-event-emitter'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { until } from '@open-draft/until'\nimport type { HttpRequestEventMap } from '../glossary'\nimport { emitAsync } from './emitAsync'\nimport { kResponsePromise, RequestController } from '../RequestController'\nimport {\n createServerErrorResponse,\n isResponseError,\n ResponseError,\n} from './responseUtils'\nimport { InterceptorError } from '../InterceptorError'\nimport { isNodeLikeError } from './isNodeLikeError'\n\ninterface HandleRequestOptions {\n requestId: string\n request: Request\n emitter: Emitter\n controller: RequestController\n\n /**\n * Called when the request has been handled\n * with the given `Response` instance.\n */\n onResponse: (response: Response) => void | Promise\n\n /**\n * Called when the request has been handled\n * with the given `Response.error()` instance.\n */\n onRequestError: (response: ResponseError) => void\n\n /**\n * Called when an unhandled error happens during the\n * request handling. This is never a thrown error/response.\n */\n onError: (error: unknown) => void\n}\n\n/**\n * @returns {Promise} Indicates whether the request has been handled.\n */\nexport async function handleRequest(\n options: HandleRequestOptions\n): Promise {\n const handleResponse = async (response: Response | Error) => {\n if (response instanceof Error) {\n options.onError(response)\n }\n\n // Handle \"Response.error()\" instances.\n else if (isResponseError(response)) {\n options.onRequestError(response)\n } else {\n await options.onResponse(response)\n }\n\n return true\n }\n\n const handleResponseError = async (error: unknown): Promise => {\n // Forward the special interceptor error instances\n // to the developer. These must not be handled in any way.\n if (error instanceof InterceptorError) {\n throw result.error\n }\n\n // Support mocking Node.js-like errors.\n if (isNodeLikeError(error)) {\n options.onError(error)\n return true\n }\n\n // Handle thrown responses.\n if (error instanceof Response) {\n return await handleResponse(error)\n }\n\n return false\n }\n\n // Add the last \"request\" listener to check if the request\n // has been handled in any way. If it hasn't, resolve the\n // response promise with undefined.\n options.emitter.once('request', ({ requestId: pendingRequestId }) => {\n if (pendingRequestId !== options.requestId) {\n return\n }\n\n if (options.controller[kResponsePromise].state === 'pending') {\n options.controller[kResponsePromise].resolve(undefined)\n }\n })\n\n const requestAbortPromise = new DeferredPromise()\n\n /**\n * @note `signal` is not always defined in React Native.\n */\n if (options.request.signal) {\n if (options.request.signal.aborted) {\n requestAbortPromise.reject(options.request.signal.reason)\n } else {\n options.request.signal.addEventListener(\n 'abort',\n () => {\n requestAbortPromise.reject(options.request.signal.reason)\n },\n { once: true }\n )\n }\n }\n\n const result = await until(async () => {\n // Emit the \"request\" event and wait until all the listeners\n // for that event are finished (e.g. async listeners awaited).\n // By the end of this promise, the developer cannot affect the\n // request anymore.\n const requestListtenersPromise = emitAsync(options.emitter, 'request', {\n requestId: options.requestId,\n request: options.request,\n controller: options.controller,\n })\n\n await Promise.race([\n // Short-circuit the request handling promise if the request gets aborted.\n requestAbortPromise,\n requestListtenersPromise,\n options.controller[kResponsePromise],\n ])\n\n // The response promise will settle immediately once\n // the developer calls either \"respondWith\" or \"errorWith\".\n const mockedResponse = await options.controller[kResponsePromise]\n return mockedResponse\n })\n\n // Handle the request being aborted while waiting for the request listeners.\n if (requestAbortPromise.state === 'rejected') {\n options.onError(requestAbortPromise.rejectionReason)\n return true\n }\n\n if (result.error) {\n // Handle the error during the request listener execution.\n // These can be thrown responses or request errors.\n if (await handleResponseError(result.error)) {\n return true\n }\n\n // If the developer has added \"unhandledException\" listeners,\n // allow them to handle the error. They can translate it to a\n // mocked response, network error, or forward it as-is.\n if (options.emitter.listenerCount('unhandledException') > 0) {\n // Create a new request controller just for the unhandled exception case.\n // This is needed because the original controller might have been already\n // interacted with (e.g. \"respondWith\" or \"errorWith\" called on it).\n const unhandledExceptionController = new RequestController(\n options.request\n )\n\n await emitAsync(options.emitter, 'unhandledException', {\n error: result.error,\n request: options.request,\n requestId: options.requestId,\n controller: unhandledExceptionController,\n }).then(() => {\n // If all the \"unhandledException\" listeners have finished\n // but have not handled the response in any way, preemptively\n // resolve the pending response promise from the new controller.\n // This prevents it from hanging forever.\n if (\n unhandledExceptionController[kResponsePromise].state === 'pending'\n ) {\n unhandledExceptionController[kResponsePromise].resolve(undefined)\n }\n })\n\n const nextResult = await until(\n () => unhandledExceptionController[kResponsePromise]\n )\n\n /**\n * @note Handle the result of the unhandled controller\n * in the same way as the original request controller.\n * The exception here is that thrown errors within the\n * \"unhandledException\" event do NOT result in another\n * emit of the same event. They are forwarded as-is.\n */\n if (nextResult.error) {\n return handleResponseError(nextResult.error)\n }\n\n if (nextResult.data) {\n return handleResponse(nextResult.data)\n }\n }\n\n // Otherwise, coerce unhandled exceptions to a 500 Internal Server Error response.\n options.onResponse(createServerErrorResponse(result.error))\n return true\n }\n\n /**\n * Handle a mocked Response instance.\n * @note That this can also be an Error in case\n * the developer called \"errorWith\". This differentiates\n * unhandled exceptions from intended errors.\n */\n if (result.data) {\n return handleResponse(result.data)\n }\n\n // In all other cases, consider the request unhandled.\n // The interceptor must perform it as-is.\n return false\n}\n","/**\n * A function that validates if property access is possible on an object\n * without throwing. It returns `true` if the property access is possible\n * and `false` otherwise.\n *\n * Environments like miniflare will throw on property access on certain objects\n * like Request and Response, for unimplemented properties.\n */\nexport function isPropertyAccessible>(\n obj: Obj,\n key: keyof Obj\n) {\n try {\n obj[key]\n return true\n } catch {\n return false\n }\n}\n","import { isPropertyAccessible } from './isPropertyAccessible'\n\n/**\n * Creates a generic 500 Unhandled Exception response.\n */\nexport function createServerErrorResponse(body: unknown): Response {\n return new Response(\n JSON.stringify(\n body instanceof Error\n ? {\n name: body.name,\n message: body.message,\n stack: body.stack,\n }\n : body\n ),\n {\n status: 500,\n statusText: 'Unhandled Exception',\n headers: {\n 'Content-Type': 'application/json',\n },\n }\n )\n}\n\nexport type ResponseError = Response & { type: 'error' }\n\n/**\n * Check if the given response is a `Response.error()`.\n *\n * @note Some environments, like Miniflare (Cloudflare) do not\n * implement the \"Response.type\" property and throw on its access.\n * Safely check if we can access \"type\" on \"Response\" before continuing.\n * @see https://github.com/mswjs/msw/issues/1834\n */\nexport function isResponseError(response: Response): response is ResponseError {\n return isPropertyAccessible(response, 'type') && response.type === 'error'\n}\n","export function isNodeLikeError(\n error: unknown\n): error is NodeJS.ErrnoException {\n if (error == null) {\n return false\n }\n\n if (!(error instanceof Error)) {\n return false\n }\n\n return 'code' in error && 'errno' in error\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-6YM4PLBI.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-6YM4PLBI.mjs new file mode 100644 index 0000000000..0f6592117c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-6YM4PLBI.mjs @@ -0,0 +1,7 @@ +// src/glossary.ts +var IS_PATCHED_MODULE = Symbol("isPatchedModule"); + +export { + IS_PATCHED_MODULE +}; +//# sourceMappingURL=chunk-6YM4PLBI.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-6YM4PLBI.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-6YM4PLBI.mjs.map new file mode 100644 index 0000000000..cf918a1aae --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-6YM4PLBI.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/glossary.ts"],"sourcesContent":["import type { RequestController } from './RequestController'\n\nexport const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')\n\n/**\n * @note Export `RequestController` as a type only.\n * It's never meant to be created in the userland.\n */\nexport type { RequestController }\n\nexport type RequestCredentials = 'omit' | 'include' | 'same-origin'\n\nexport type HttpRequestEventMap = {\n request: [\n args: {\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n response: [\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ]\n unhandledException: [\n args: {\n error: unknown\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n}\n"],"mappings":";AAEO,IAAM,oBAAmC,OAAO,iBAAiB;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-73NOP3T5.js b/node_modules/@mswjs/interceptors/lib/node/chunk-73NOP3T5.js new file mode 100644 index 0000000000..3bcf384147 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-73NOP3T5.js @@ -0,0 +1,7 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/glossary.ts +var IS_PATCHED_MODULE = Symbol("isPatchedModule"); + + + +exports.IS_PATCHED_MODULE = IS_PATCHED_MODULE; +//# sourceMappingURL=chunk-73NOP3T5.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-73NOP3T5.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-73NOP3T5.js.map new file mode 100644 index 0000000000..6615ceaf1c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-73NOP3T5.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/glossary.ts"],"names":[],"mappings":";AAEO,IAAM,oBAAmC,OAAO,iBAAiB","sourcesContent":["import type { RequestController } from './RequestController'\n\nexport const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')\n\n/**\n * @note Export `RequestController` as a type only.\n * It's never meant to be created in the userland.\n */\nexport type { RequestController }\n\nexport type RequestCredentials = 'omit' | 'include' | 'same-origin'\n\nexport type HttpRequestEventMap = {\n request: [\n args: {\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n response: [\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ]\n unhandledException: [\n args: {\n error: unknown\n request: Request\n requestId: string\n controller: RequestController\n }\n ]\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-CTGTMEFD.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-CTGTMEFD.mjs new file mode 100644 index 0000000000..d9bb95584e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-CTGTMEFD.mjs @@ -0,0 +1,310 @@ +import { + hasConfigurableGlobal +} from "./chunk-TX5GBTFY.mjs"; +import { + IS_PATCHED_MODULE +} from "./chunk-6YM4PLBI.mjs"; +import { + RequestController, + emitAsync, + handleRequest +} from "./chunk-5KMS5CTP.mjs"; +import { + FetchResponse, + Interceptor, + createRequestId +} from "./chunk-I7HQIBT7.mjs"; + +// src/interceptors/fetch/index.ts +import { invariant } from "outvariant"; +import { DeferredPromise } from "@open-draft/deferred-promise"; + +// src/utils/canParseUrl.ts +function canParseUrl(url) { + try { + new URL(url); + return true; + } catch (_error) { + return false; + } +} + +// src/interceptors/fetch/utils/createNetworkError.ts +function createNetworkError(cause) { + return Object.assign(new TypeError("Failed to fetch"), { + cause + }); +} + +// src/interceptors/fetch/utils/followRedirect.ts +var REQUEST_BODY_HEADERS = [ + "content-encoding", + "content-language", + "content-location", + "content-type", + "content-length" +]; +var kRedirectCount = Symbol("kRedirectCount"); +async function followFetchRedirect(request, response) { + if (response.status !== 303 && request.body != null) { + return Promise.reject(createNetworkError()); + } + const requestUrl = new URL(request.url); + let locationUrl; + try { + locationUrl = new URL(response.headers.get("location"), request.url); + } catch (error) { + return Promise.reject(createNetworkError(error)); + } + if (!(locationUrl.protocol === "http:" || locationUrl.protocol === "https:")) { + return Promise.reject( + createNetworkError("URL scheme must be a HTTP(S) scheme") + ); + } + if (Reflect.get(request, kRedirectCount) > 20) { + return Promise.reject(createNetworkError("redirect count exceeded")); + } + Object.defineProperty(request, kRedirectCount, { + value: (Reflect.get(request, kRedirectCount) || 0) + 1 + }); + if (request.mode === "cors" && (locationUrl.username || locationUrl.password) && !sameOrigin(requestUrl, locationUrl)) { + return Promise.reject( + createNetworkError('cross origin not allowed for request mode "cors"') + ); + } + const requestInit = {}; + if ([301, 302].includes(response.status) && request.method === "POST" || response.status === 303 && !["HEAD", "GET"].includes(request.method)) { + requestInit.method = "GET"; + requestInit.body = null; + REQUEST_BODY_HEADERS.forEach((headerName) => { + request.headers.delete(headerName); + }); + } + if (!sameOrigin(requestUrl, locationUrl)) { + request.headers.delete("authorization"); + request.headers.delete("proxy-authorization"); + request.headers.delete("cookie"); + request.headers.delete("host"); + } + requestInit.headers = request.headers; + return fetch(new Request(locationUrl, requestInit)); +} +function sameOrigin(left, right) { + if (left.origin === right.origin && left.origin === "null") { + return true; + } + if (left.protocol === right.protocol && left.hostname === right.hostname && left.port === right.port) { + return true; + } + return false; +} + +// src/interceptors/fetch/utils/brotli-decompress.ts +import zlib from "zlib"; +var BrotliDecompressionStream = class extends TransformStream { + constructor() { + const decompress = zlib.createBrotliDecompress({ + flush: zlib.constants.BROTLI_OPERATION_FLUSH, + finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH + }); + super({ + async transform(chunk, controller) { + const buffer = Buffer.from(chunk); + const decompressed = await new Promise((resolve, reject) => { + decompress.write(buffer, (error) => { + if (error) + reject(error); + }); + decompress.flush(); + decompress.once("data", (data) => resolve(data)); + decompress.once("error", (error) => reject(error)); + decompress.once("end", () => controller.terminate()); + }).catch((error) => { + controller.error(error); + }); + controller.enqueue(decompressed); + } + }); + } +}; + +// src/interceptors/fetch/utils/decompression.ts +var PipelineStream = class extends TransformStream { + constructor(transformStreams, ...strategies) { + super({}, ...strategies); + const readable = [super.readable, ...transformStreams].reduce( + (readable2, transform) => readable2.pipeThrough(transform) + ); + Object.defineProperty(this, "readable", { + get() { + return readable; + } + }); + } +}; +function parseContentEncoding(contentEncoding) { + return contentEncoding.toLowerCase().split(",").map((coding) => coding.trim()); +} +function createDecompressionStream(contentEncoding) { + if (contentEncoding === "") { + return null; + } + const codings = parseContentEncoding(contentEncoding); + if (codings.length === 0) { + return null; + } + const transformers = codings.reduceRight( + (transformers2, coding) => { + if (coding === "gzip" || coding === "x-gzip") { + return transformers2.concat(new DecompressionStream("gzip")); + } else if (coding === "deflate") { + return transformers2.concat(new DecompressionStream("deflate")); + } else if (coding === "br") { + return transformers2.concat(new BrotliDecompressionStream()); + } else { + transformers2.length = 0; + } + return transformers2; + }, + [] + ); + return new PipelineStream(transformers); +} +function decompressResponse(response) { + if (response.body === null) { + return null; + } + const decompressionStream = createDecompressionStream( + response.headers.get("content-encoding") || "" + ); + if (!decompressionStream) { + return null; + } + response.body.pipeTo(decompressionStream.writable); + return decompressionStream.readable; +} + +// src/interceptors/fetch/index.ts +var _FetchInterceptor = class extends Interceptor { + constructor() { + super(_FetchInterceptor.symbol); + } + checkEnvironment() { + return hasConfigurableGlobal("fetch"); + } + async setup() { + const pureFetch = globalThis.fetch; + invariant( + !pureFetch[IS_PATCHED_MODULE], + 'Failed to patch the "fetch" module: already patched.' + ); + globalThis.fetch = async (input, init) => { + const requestId = createRequestId(); + const resolvedInput = typeof input === "string" && typeof location !== "undefined" && !canParseUrl(input) ? new URL(input, location.origin) : input; + const request = new Request(resolvedInput, init); + const responsePromise = new DeferredPromise(); + const controller = new RequestController(request); + this.logger.info("[%s] %s", request.method, request.url); + this.logger.info("awaiting for the mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + this.emitter.listenerCount("request") + ); + const isRequestHandled = await handleRequest({ + request, + requestId, + emitter: this.emitter, + controller, + onResponse: async (rawResponse) => { + this.logger.info("received mocked response!", { + rawResponse + }); + const decompressedStream = decompressResponse(rawResponse); + const response = decompressedStream === null ? rawResponse : new FetchResponse(decompressedStream, rawResponse); + FetchResponse.setUrl(request.url, response); + if (FetchResponse.isRedirectResponse(response.status)) { + if (request.redirect === "error") { + responsePromise.reject(createNetworkError("unexpected redirect")); + return; + } + if (request.redirect === "follow") { + followFetchRedirect(request, response).then( + (response2) => { + responsePromise.resolve(response2); + }, + (reason) => { + responsePromise.reject(reason); + } + ); + return; + } + } + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + await emitAsync(this.emitter, "response", { + // Clone the mocked response for the "response" event listener. + // This way, the listener can read the response and not lock its body + // for the actual fetch consumer. + response: response.clone(), + isMockedResponse: true, + request, + requestId + }); + } + responsePromise.resolve(response); + }, + onRequestError: (response) => { + this.logger.info("request has errored!", { response }); + responsePromise.reject(createNetworkError(response)); + }, + onError: (error) => { + this.logger.info("request has been aborted!", { error }); + responsePromise.reject(error); + } + }); + if (isRequestHandled) { + this.logger.info("request has been handled, returning mock promise..."); + return responsePromise; + } + this.logger.info( + "no mocked response received, performing request as-is..." + ); + return pureFetch(request).then(async (response) => { + this.logger.info("original fetch performed", response); + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + const responseClone = response.clone(); + await emitAsync(this.emitter, "response", { + response: responseClone, + isMockedResponse: false, + request, + requestId + }); + } + return response; + }); + }; + Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.fetch = pureFetch; + this.logger.info( + 'restored native "globalThis.fetch"!', + globalThis.fetch.name + ); + }); + } +}; +var FetchInterceptor = _FetchInterceptor; +FetchInterceptor.symbol = Symbol("fetch"); + +export { + FetchInterceptor +}; +//# sourceMappingURL=chunk-CTGTMEFD.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-CTGTMEFD.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-CTGTMEFD.mjs.map new file mode 100644 index 0000000000..0a272481e6 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-CTGTMEFD.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/fetch/index.ts","../../src/utils/canParseUrl.ts","../../src/interceptors/fetch/utils/createNetworkError.ts","../../src/interceptors/fetch/utils/followRedirect.ts","../../src/interceptors/fetch/utils/brotli-decompress.ts","../../src/interceptors/fetch/utils/decompression.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { RequestController } from '../../RequestController'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { handleRequest } from '../../utils/handleRequest'\nimport { canParseUrl } from '../../utils/canParseUrl'\nimport { createRequestId } from '../../createRequestId'\nimport { createNetworkError } from './utils/createNetworkError'\nimport { followFetchRedirect } from './utils/followRedirect'\nimport { decompressResponse } from './utils/decompression'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\nimport { FetchResponse } from '../../utils/fetchUtils'\n\nexport class FetchInterceptor extends Interceptor {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('fetch')\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = createRequestId()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n const responsePromise = new DeferredPromise()\n const controller = new RequestController(request)\n\n this.logger.info('[%s] %s', request.method, request.url)\n this.logger.info('awaiting for the mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n emitter: this.emitter,\n controller,\n onResponse: async (rawResponse) => {\n this.logger.info('received mocked response!', {\n rawResponse,\n })\n\n // Decompress the mocked response body, if applicable.\n const decompressedStream = decompressResponse(rawResponse)\n const response =\n decompressedStream === null\n ? rawResponse\n : new FetchResponse(decompressedStream, rawResponse)\n\n FetchResponse.setUrl(request.url, response)\n\n /**\n * Undici's handling of following redirect responses.\n * Treat the \"manual\" redirect mode as a regular mocked response.\n * This way, the client can manually follow the redirect it receives.\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173\n */\n if (FetchResponse.isRedirectResponse(response.status)) {\n // Reject the request promise if its `redirect` is set to `error`\n // and it receives a mocked redirect response.\n if (request.redirect === 'error') {\n responsePromise.reject(createNetworkError('unexpected redirect'))\n return\n }\n\n if (request.redirect === 'follow') {\n followFetchRedirect(request, response).then(\n (response) => {\n responsePromise.resolve(response)\n },\n (reason) => {\n responsePromise.reject(reason)\n }\n )\n return\n }\n }\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n // Await the response listeners to finish before resolving\n // the response promise. This ensures all your logic finishes\n // before the interceptor resolves the pending response.\n await emitAsync(this.emitter, 'response', {\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n response: response.clone(),\n isMockedResponse: true,\n request,\n requestId,\n })\n }\n\n responsePromise.resolve(response)\n },\n onRequestError: (response) => {\n this.logger.info('request has errored!', { response })\n responsePromise.reject(createNetworkError(response))\n },\n onError: (error) => {\n this.logger.info('request has been aborted!', { error })\n responsePromise.reject(error)\n },\n })\n\n if (isRequestHandled) {\n this.logger.info('request has been handled, returning mock promise...')\n return responsePromise\n }\n\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n\n return pureFetch(request).then(async (response) => {\n this.logger.info('original fetch performed', response)\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n const responseClone = response.clone()\n\n await emitAsync(this.emitter, 'response', {\n response: responseClone,\n isMockedResponse: false,\n request,\n requestId,\n })\n }\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n","export function createNetworkError(cause?: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","import { createNetworkError } from './createNetworkError'\n\nconst REQUEST_BODY_HEADERS = [\n 'content-encoding',\n 'content-language',\n 'content-location',\n 'content-type',\n 'content-length',\n]\n\nconst kRedirectCount = Symbol('kRedirectCount')\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1210\n */\nexport async function followFetchRedirect(\n request: Request,\n response: Response\n): Promise {\n if (response.status !== 303 && request.body != null) {\n return Promise.reject(createNetworkError())\n }\n\n const requestUrl = new URL(request.url)\n\n let locationUrl: URL\n try {\n // If the location is a relative URL, use the request URL as the base URL.\n locationUrl = new URL(response.headers.get('location')!, request.url) \n } catch (error) {\n return Promise.reject(createNetworkError(error))\n }\n\n if (\n !(locationUrl.protocol === 'http:' || locationUrl.protocol === 'https:')\n ) {\n return Promise.reject(\n createNetworkError('URL scheme must be a HTTP(S) scheme')\n )\n }\n\n if (Reflect.get(request, kRedirectCount) > 20) {\n return Promise.reject(createNetworkError('redirect count exceeded'))\n }\n\n Object.defineProperty(request, kRedirectCount, {\n value: (Reflect.get(request, kRedirectCount) || 0) + 1,\n })\n\n if (\n request.mode === 'cors' &&\n (locationUrl.username || locationUrl.password) &&\n !sameOrigin(requestUrl, locationUrl)\n ) {\n return Promise.reject(\n createNetworkError('cross origin not allowed for request mode \"cors\"')\n )\n }\n\n const requestInit: RequestInit = {}\n\n if (\n ([301, 302].includes(response.status) && request.method === 'POST') ||\n (response.status === 303 && !['HEAD', 'GET'].includes(request.method))\n ) {\n requestInit.method = 'GET'\n requestInit.body = null\n\n REQUEST_BODY_HEADERS.forEach((headerName) => {\n request.headers.delete(headerName)\n })\n }\n\n if (!sameOrigin(requestUrl, locationUrl)) {\n request.headers.delete('authorization')\n request.headers.delete('proxy-authorization')\n request.headers.delete('cookie')\n request.headers.delete('host')\n }\n\n /**\n * @note Undici \"safely\" extracts the request body.\n * I suspect we cannot dispatch this request again\n * since its body has been read and the stream is locked.\n */\n\n requestInit.headers = request.headers\n return fetch(new Request(locationUrl, requestInit))\n}\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/util.js#L761\n */\nfunction sameOrigin(left: URL, right: URL): boolean {\n if (left.origin === right.origin && left.origin === 'null') {\n return true\n }\n\n if (\n left.protocol === right.protocol &&\n left.hostname === right.hostname &&\n left.port === right.port\n ) {\n return true\n }\n\n return false\n}\n","import zlib from 'node:zlib'\n\nexport class BrotliDecompressionStream extends TransformStream {\n constructor() {\n const decompress = zlib.createBrotliDecompress({\n flush: zlib.constants.BROTLI_OPERATION_FLUSH,\n finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH,\n })\n\n super({\n async transform(chunk, controller) {\n const buffer = Buffer.from(chunk)\n\n const decompressed = await new Promise((resolve, reject) => {\n decompress.write(buffer, (error) => {\n if (error) reject(error)\n })\n\n decompress.flush()\n decompress.once('data', (data) => resolve(data))\n decompress.once('error', (error) => reject(error))\n decompress.once('end', () => controller.terminate())\n }).catch((error) => {\n controller.error(error)\n })\n\n controller.enqueue(decompressed)\n },\n })\n }\n}\n","// Import from an internal alias that resolves to different modules\n// depending on the environment. This way, we can keep the fetch interceptor\n// intact while using different strategies for Brotli decompression.\nimport { BrotliDecompressionStream } from 'internal:brotli-decompress'\n\nclass PipelineStream extends TransformStream {\n constructor(\n transformStreams: Array,\n ...strategies: Array\n ) {\n super({}, ...strategies)\n\n const readable = [super.readable as any, ...transformStreams].reduce(\n (readable, transform) => readable.pipeThrough(transform)\n )\n\n Object.defineProperty(this, 'readable', {\n get() {\n return readable\n },\n })\n }\n}\n\nexport function parseContentEncoding(contentEncoding: string): Array {\n return contentEncoding\n .toLowerCase()\n .split(',')\n .map((coding) => coding.trim())\n}\n\nfunction createDecompressionStream(\n contentEncoding: string\n): TransformStream | null {\n if (contentEncoding === '') {\n return null\n }\n\n const codings = parseContentEncoding(contentEncoding)\n\n if (codings.length === 0) {\n return null\n }\n\n const transformers = codings.reduceRight>(\n (transformers, coding) => {\n if (coding === 'gzip' || coding === 'x-gzip') {\n return transformers.concat(new DecompressionStream('gzip'))\n } else if (coding === 'deflate') {\n return transformers.concat(new DecompressionStream('deflate'))\n } else if (coding === 'br') {\n return transformers.concat(new BrotliDecompressionStream())\n } else {\n transformers.length = 0\n }\n\n return transformers\n },\n []\n )\n\n return new PipelineStream(transformers)\n}\n\nexport function decompressResponse(\n response: Response\n): ReadableStream | null {\n if (response.body === null) {\n return null\n }\n\n const decompressionStream = createDecompressionStream(\n response.headers.get('content-encoding') || ''\n )\n\n if (!decompressionStream) {\n return null\n }\n\n // Use `pipeTo` and return the decompression stream's readable\n // instead of `pipeThrough` because that will lock the original\n // response stream, making it unusable as the input to Response.\n response.body.pipeTo(decompressionStream.writable)\n return decompressionStream.readable\n}\n"],"mappings":"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","names":["readable","transformers","response"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-I7HQIBT7.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-I7HQIBT7.mjs new file mode 100644 index 0000000000..5db4fec284 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-I7HQIBT7.mjs @@ -0,0 +1,245 @@ +// src/Interceptor.ts +import { Logger } from "@open-draft/logger"; +import { Emitter } from "strict-event-emitter"; +var INTERNAL_REQUEST_ID_HEADER_NAME = "x-interceptors-internal-request-id"; +function getGlobalSymbol(symbol) { + return ( + // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587 + globalThis[symbol] || void 0 + ); +} +function setGlobalSymbol(symbol, value) { + globalThis[symbol] = value; +} +function deleteGlobalSymbol(symbol) { + delete globalThis[symbol]; +} +var InterceptorReadyState = /* @__PURE__ */ ((InterceptorReadyState2) => { + InterceptorReadyState2["INACTIVE"] = "INACTIVE"; + InterceptorReadyState2["APPLYING"] = "APPLYING"; + InterceptorReadyState2["APPLIED"] = "APPLIED"; + InterceptorReadyState2["DISPOSING"] = "DISPOSING"; + InterceptorReadyState2["DISPOSED"] = "DISPOSED"; + return InterceptorReadyState2; +})(InterceptorReadyState || {}); +var Interceptor = class { + constructor(symbol) { + this.symbol = symbol; + this.readyState = "INACTIVE" /* INACTIVE */; + this.emitter = new Emitter(); + this.subscriptions = []; + this.logger = new Logger(symbol.description); + this.emitter.setMaxListeners(0); + this.logger.info("constructing the interceptor..."); + } + /** + * Determine if this interceptor can be applied + * in the current environment. + */ + checkEnvironment() { + return true; + } + /** + * Apply this interceptor to the current process. + * Returns an already running interceptor instance if it's present. + */ + apply() { + const logger = this.logger.extend("apply"); + logger.info("applying the interceptor..."); + if (this.readyState === "APPLIED" /* APPLIED */) { + logger.info("intercepted already applied!"); + return; + } + const shouldApply = this.checkEnvironment(); + if (!shouldApply) { + logger.info("the interceptor cannot be applied in this environment!"); + return; + } + this.readyState = "APPLYING" /* APPLYING */; + const runningInstance = this.getInstance(); + if (runningInstance) { + logger.info("found a running instance, reusing..."); + this.on = (event, listener) => { + logger.info('proxying the "%s" listener', event); + runningInstance.emitter.addListener(event, listener); + this.subscriptions.push(() => { + runningInstance.emitter.removeListener(event, listener); + logger.info('removed proxied "%s" listener!', event); + }); + return this; + }; + this.readyState = "APPLIED" /* APPLIED */; + return; + } + logger.info("no running instance found, setting up a new instance..."); + this.setup(); + this.setInstance(); + this.readyState = "APPLIED" /* APPLIED */; + } + /** + * Setup the module augments and stubs necessary for this interceptor. + * This method is not run if there's a running interceptor instance + * to prevent instantiating an interceptor multiple times. + */ + setup() { + } + /** + * Listen to the interceptor's public events. + */ + on(event, listener) { + const logger = this.logger.extend("on"); + if (this.readyState === "DISPOSING" /* DISPOSING */ || this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot listen to events, already disposed!"); + return this; + } + logger.info('adding "%s" event listener:', event, listener); + this.emitter.on(event, listener); + return this; + } + once(event, listener) { + this.emitter.once(event, listener); + return this; + } + off(event, listener) { + this.emitter.off(event, listener); + return this; + } + removeAllListeners(event) { + this.emitter.removeAllListeners(event); + return this; + } + /** + * Disposes of any side-effects this interceptor has introduced. + */ + dispose() { + const logger = this.logger.extend("dispose"); + if (this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot dispose, already disposed!"); + return; + } + logger.info("disposing the interceptor..."); + this.readyState = "DISPOSING" /* DISPOSING */; + if (!this.getInstance()) { + logger.info("no interceptors running, skipping dispose..."); + return; + } + this.clearInstance(); + logger.info("global symbol deleted:", getGlobalSymbol(this.symbol)); + if (this.subscriptions.length > 0) { + logger.info("disposing of %d subscriptions...", this.subscriptions.length); + for (const dispose of this.subscriptions) { + dispose(); + } + this.subscriptions = []; + logger.info("disposed of all subscriptions!", this.subscriptions.length); + } + this.emitter.removeAllListeners(); + logger.info("destroyed the listener!"); + this.readyState = "DISPOSED" /* DISPOSED */; + } + getInstance() { + var _a; + const instance = getGlobalSymbol(this.symbol); + this.logger.info("retrieved global instance:", (_a = instance == null ? void 0 : instance.constructor) == null ? void 0 : _a.name); + return instance; + } + setInstance() { + setGlobalSymbol(this.symbol, this); + this.logger.info("set global instance!", this.symbol.description); + } + clearInstance() { + deleteGlobalSymbol(this.symbol); + this.logger.info("cleared global instance!", this.symbol.description); + } +}; + +// src/createRequestId.ts +function createRequestId() { + return Math.random().toString(16).slice(2); +} + +// src/utils/fetchUtils.ts +var _FetchResponse = class extends Response { + static isConfigurableStatusCode(status) { + return status >= 200 && status <= 599; + } + static isRedirectResponse(status) { + return _FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status); + } + /** + * Returns a boolean indicating whether the given response status + * code represents a response that can have a body. + */ + static isResponseWithBody(status) { + return !_FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status); + } + static setUrl(url, response) { + if (!url) { + return; + } + if (response.url != "") { + return; + } + Object.defineProperty(response, "url", { + value: url, + enumerable: true, + configurable: true, + writable: false + }); + } + /** + * Parses the given raw HTTP headers into a Fetch API `Headers` instance. + */ + static parseRawHeaders(rawHeaders) { + const headers = new Headers(); + for (let line = 0; line < rawHeaders.length; line += 2) { + headers.append(rawHeaders[line], rawHeaders[line + 1]); + } + return headers; + } + constructor(body, init = {}) { + var _a; + const status = (_a = init.status) != null ? _a : 200; + const safeStatus = _FetchResponse.isConfigurableStatusCode(status) ? status : 200; + const finalBody = _FetchResponse.isResponseWithBody(status) ? body : null; + super(finalBody, { + ...init, + status: safeStatus + }); + if (status !== safeStatus) { + const stateSymbol = Object.getOwnPropertySymbols(this).find( + (symbol) => symbol.description === "state" + ); + if (stateSymbol) { + const state = Reflect.get(this, stateSymbol); + Reflect.set(state, "status", status); + } else { + Object.defineProperty(this, "status", { + value: status, + enumerable: true, + configurable: true, + writable: false + }); + } + } + _FetchResponse.setUrl(init.url, this); + } +}; +var FetchResponse = _FetchResponse; +/** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ +FetchResponse.STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]; +FetchResponse.STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]; + +export { + INTERNAL_REQUEST_ID_HEADER_NAME, + getGlobalSymbol, + deleteGlobalSymbol, + InterceptorReadyState, + Interceptor, + createRequestId, + FetchResponse +}; +//# sourceMappingURL=chunk-I7HQIBT7.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-I7HQIBT7.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-I7HQIBT7.mjs.map new file mode 100644 index 0000000000..1e38f2cb4f --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-I7HQIBT7.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/Interceptor.ts","../../src/createRequestId.ts","../../src/utils/fetchUtils.ts"],"sourcesContent":["import { Logger } from '@open-draft/logger'\nimport { Emitter, Listener } from 'strict-event-emitter'\n\nexport type InterceptorEventMap = Record\nexport type InterceptorSubscription = () => void\n\n/**\n * Request header name to detect when a single request\n * is being handled by nested interceptors (XHR -> ClientRequest).\n * Obscure by design to prevent collisions with user-defined headers.\n * Ideally, come up with the Interceptor-level mechanism for this.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\nexport const INTERNAL_REQUEST_ID_HEADER_NAME =\n 'x-interceptors-internal-request-id'\n\nexport function getGlobalSymbol(symbol: Symbol): V | undefined {\n return (\n // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587\n globalThis[symbol] || undefined\n )\n}\n\nfunction setGlobalSymbol(symbol: Symbol, value: any): void {\n // @ts-ignore\n globalThis[symbol] = value\n}\n\nexport function deleteGlobalSymbol(symbol: Symbol): void {\n // @ts-ignore\n delete globalThis[symbol]\n}\n\nexport enum InterceptorReadyState {\n INACTIVE = 'INACTIVE',\n APPLYING = 'APPLYING',\n APPLIED = 'APPLIED',\n DISPOSING = 'DISPOSING',\n DISPOSED = 'DISPOSED',\n}\n\nexport type ExtractEventNames> =\n Events extends Record ? EventName : never\n\nexport class Interceptor {\n protected emitter: Emitter\n protected subscriptions: Array\n protected logger: Logger\n\n public readyState: InterceptorReadyState\n\n constructor(private readonly symbol: symbol) {\n this.readyState = InterceptorReadyState.INACTIVE\n\n this.emitter = new Emitter()\n this.subscriptions = []\n this.logger = new Logger(symbol.description!)\n\n // Do not limit the maximum number of listeners\n // so not to limit the maximum amount of parallel events emitted.\n this.emitter.setMaxListeners(0)\n\n this.logger.info('constructing the interceptor...')\n }\n\n /**\n * Determine if this interceptor can be applied\n * in the current environment.\n */\n protected checkEnvironment(): boolean {\n return true\n }\n\n /**\n * Apply this interceptor to the current process.\n * Returns an already running interceptor instance if it's present.\n */\n public apply(): void {\n const logger = this.logger.extend('apply')\n logger.info('applying the interceptor...')\n\n if (this.readyState === InterceptorReadyState.APPLIED) {\n logger.info('intercepted already applied!')\n return\n }\n\n const shouldApply = this.checkEnvironment()\n\n if (!shouldApply) {\n logger.info('the interceptor cannot be applied in this environment!')\n return\n }\n\n this.readyState = InterceptorReadyState.APPLYING\n\n // Whenever applying a new interceptor, check if it hasn't been applied already.\n // This enables to apply the same interceptor multiple times, for example from a different\n // interceptor, only proxying events but keeping the stubs in a single place.\n const runningInstance = this.getInstance()\n\n if (runningInstance) {\n logger.info('found a running instance, reusing...')\n\n // Proxy any listeners you set on this instance to the running instance.\n this.on = (event, listener) => {\n logger.info('proxying the \"%s\" listener', event)\n\n // Add listeners to the running instance so they appear\n // at the top of the event listeners list and are executed first.\n runningInstance.emitter.addListener(event, listener)\n\n // Ensure that once this interceptor instance is disposed,\n // it removes all listeners it has appended to the running interceptor instance.\n this.subscriptions.push(() => {\n runningInstance.emitter.removeListener(event, listener)\n logger.info('removed proxied \"%s\" listener!', event)\n })\n\n return this\n }\n\n this.readyState = InterceptorReadyState.APPLIED\n\n return\n }\n\n logger.info('no running instance found, setting up a new instance...')\n\n // Setup the interceptor.\n this.setup()\n\n // Store the newly applied interceptor instance globally.\n this.setInstance()\n\n this.readyState = InterceptorReadyState.APPLIED\n }\n\n /**\n * Setup the module augments and stubs necessary for this interceptor.\n * This method is not run if there's a running interceptor instance\n * to prevent instantiating an interceptor multiple times.\n */\n protected setup(): void {}\n\n /**\n * Listen to the interceptor's public events.\n */\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n const logger = this.logger.extend('on')\n\n if (\n this.readyState === InterceptorReadyState.DISPOSING ||\n this.readyState === InterceptorReadyState.DISPOSED\n ) {\n logger.info('cannot listen to events, already disposed!')\n return this\n }\n\n logger.info('adding \"%s\" event listener:', event, listener)\n\n this.emitter.on(event, listener)\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.once(event, listener)\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.off(event, listener)\n return this\n }\n\n public removeAllListeners>(\n event?: EventName\n ): this {\n this.emitter.removeAllListeners(event)\n return this\n }\n\n /**\n * Disposes of any side-effects this interceptor has introduced.\n */\n public dispose(): void {\n const logger = this.logger.extend('dispose')\n\n if (this.readyState === InterceptorReadyState.DISPOSED) {\n logger.info('cannot dispose, already disposed!')\n return\n }\n\n logger.info('disposing the interceptor...')\n this.readyState = InterceptorReadyState.DISPOSING\n\n if (!this.getInstance()) {\n logger.info('no interceptors running, skipping dispose...')\n return\n }\n\n // Delete the global symbol as soon as possible,\n // indicating that the interceptor is no longer running.\n this.clearInstance()\n\n logger.info('global symbol deleted:', getGlobalSymbol(this.symbol))\n\n if (this.subscriptions.length > 0) {\n logger.info('disposing of %d subscriptions...', this.subscriptions.length)\n\n for (const dispose of this.subscriptions) {\n dispose()\n }\n\n this.subscriptions = []\n\n logger.info('disposed of all subscriptions!', this.subscriptions.length)\n }\n\n this.emitter.removeAllListeners()\n logger.info('destroyed the listener!')\n\n this.readyState = InterceptorReadyState.DISPOSED\n }\n\n private getInstance(): this | undefined {\n const instance = getGlobalSymbol(this.symbol)\n this.logger.info('retrieved global instance:', instance?.constructor?.name)\n return instance\n }\n\n private setInstance(): void {\n setGlobalSymbol(this.symbol, this)\n this.logger.info('set global instance!', this.symbol.description)\n }\n\n private clearInstance(): void {\n deleteGlobalSymbol(this.symbol)\n this.logger.info('cleared global instance!', this.symbol.description)\n }\n}\n","/**\n * Generate a random ID string to represent a request.\n * @example\n * createRequestId()\n * // \"f774b6c9c600f\"\n */\nexport function createRequestId(): string {\n return Math.random().toString(16).slice(2)\n}\n","export interface FetchResponseInit extends ResponseInit {\n url?: string\n}\n\nexport class FetchResponse extends Response {\n /**\n * Response status codes for responses that cannot have body.\n * @see https://fetch.spec.whatwg.org/#statuses\n */\n static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n static isConfigurableStatusCode(status: number): boolean {\n return status >= 200 && status <= 599\n }\n\n static isRedirectResponse(status: number): boolean {\n return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n }\n\n /**\n * Returns a boolean indicating whether the given response status\n * code represents a response that can have a body.\n */\n static isResponseWithBody(status: number): boolean {\n return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n }\n\n static setUrl(url: string | undefined, response: Response): void {\n if (!url) {\n return\n }\n\n if (response.url != '') {\n return\n }\n\n Object.defineProperty(response, 'url', {\n value: url,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n /**\n * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n */\n static parseRawHeaders(rawHeaders: Array): Headers {\n const headers = new Headers()\n for (let line = 0; line < rawHeaders.length; line += 2) {\n headers.append(rawHeaders[line], rawHeaders[line + 1])\n }\n return headers\n }\n\n constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n const status = init.status ?? 200\n const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n ? status\n : 200\n const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n super(finalBody, {\n ...init,\n status: safeStatus,\n })\n\n if (status !== safeStatus) {\n /**\n * @note Undici keeps an internal \"Symbol(state)\" that holds\n * the actual value of response status. Update that in Node.js.\n */\n const stateSymbol = Object.getOwnPropertySymbols(this).find(\n (symbol) => symbol.description === 'state'\n )\n if (stateSymbol) {\n const state = Reflect.get(this, stateSymbol) as object\n Reflect.set(state, 'status', status)\n } else {\n Object.defineProperty(this, 'status', {\n value: status,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n\n FetchResponse.setUrl(init.url, this)\n }\n}\n"],"mappings":"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","names":["InterceptorReadyState"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-LCA4FKWY.js b/node_modules/@mswjs/interceptors/lib/node/chunk-LCA4FKWY.js new file mode 100644 index 0000000000..e386d612df --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-LCA4FKWY.js @@ -0,0 +1,844 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + + + +var _chunkLK6DILFKjs = require('./chunk-LK6DILFK.js'); + + +var _chunkPFGO5BSMjs = require('./chunk-PFGO5BSM.js'); + + +var _chunk73NOP3T5js = require('./chunk-73NOP3T5.js'); + + + +var _chunk6L3PFBGTjs = require('./chunk-6L3PFBGT.js'); + + + + + +var _chunkWZTE4PCOjs = require('./chunk-WZTE4PCO.js'); + +// src/interceptors/XMLHttpRequest/index.ts +var _outvariant = require('outvariant'); + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts + +var _isnodeprocess = require('is-node-process'); + +// src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +function concatArrayBuffer(left, right) { + const result = new Uint8Array(left.byteLength + right.byteLength); + result.set(left, 0); + result.set(right, left.byteLength); + return result; +} + +// src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +var EventPolyfill = class { + constructor(type, options) { + this.NONE = 0; + this.CAPTURING_PHASE = 1; + this.AT_TARGET = 2; + this.BUBBLING_PHASE = 3; + this.type = ""; + this.srcElement = null; + this.currentTarget = null; + this.eventPhase = 0; + this.isTrusted = true; + this.composed = false; + this.cancelable = true; + this.defaultPrevented = false; + this.bubbles = true; + this.lengthComputable = true; + this.loaded = 0; + this.total = 0; + this.cancelBubble = false; + this.returnValue = true; + this.type = type; + this.target = (options == null ? void 0 : options.target) || null; + this.currentTarget = (options == null ? void 0 : options.currentTarget) || null; + this.timeStamp = Date.now(); + } + composedPath() { + return []; + } + initEvent(type, bubbles, cancelable) { + this.type = type; + this.bubbles = !!bubbles; + this.cancelable = !!cancelable; + } + preventDefault() { + this.defaultPrevented = true; + } + stopPropagation() { + } + stopImmediatePropagation() { + } +}; + +// src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +var ProgressEventPolyfill = class extends EventPolyfill { + constructor(type, init) { + super(type); + this.lengthComputable = (init == null ? void 0 : init.lengthComputable) || false; + this.composed = (init == null ? void 0 : init.composed) || false; + this.loaded = (init == null ? void 0 : init.loaded) || 0; + this.total = (init == null ? void 0 : init.total) || 0; + } +}; + +// src/interceptors/XMLHttpRequest/utils/createEvent.ts +var SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== "undefined"; +function createEvent(target, type, init) { + const progressEvents = [ + "error", + "progress", + "loadstart", + "loadend", + "load", + "timeout", + "abort" + ]; + const ProgressEventClass = SUPPORTS_PROGRESS_EVENT ? ProgressEvent : ProgressEventPolyfill; + const event = progressEvents.includes(type) ? new ProgressEventClass(type, { + lengthComputable: true, + loaded: (init == null ? void 0 : init.loaded) || 0, + total: (init == null ? void 0 : init.total) || 0 + }) : new EventPolyfill(type, { + target, + currentTarget: target + }); + return event; +} + +// src/utils/findPropertySource.ts +function findPropertySource(target, propertyName) { + if (!(propertyName in target)) { + return null; + } + const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName); + if (hasProperty) { + return target; + } + const prototype = Reflect.getPrototypeOf(target); + return prototype ? findPropertySource(prototype, propertyName) : null; +} + +// src/utils/createProxy.ts +function createProxy(target, options) { + const proxy = new Proxy(target, optionsToProxyHandler(options)); + return proxy; +} +function optionsToProxyHandler(options) { + const { constructorCall, methodCall, getProperty, setProperty } = options; + const handler = {}; + if (typeof constructorCall !== "undefined") { + handler.construct = function(target, args, newTarget) { + const next = Reflect.construct.bind(null, target, args, newTarget); + return constructorCall.call(newTarget, args, next); + }; + } + handler.set = function(target, propertyName, nextValue) { + const next = () => { + const propertySource = findPropertySource(target, propertyName) || target; + const ownDescriptors = Reflect.getOwnPropertyDescriptor( + propertySource, + propertyName + ); + if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") { + ownDescriptors.set.apply(target, [nextValue]); + return true; + } + return Reflect.defineProperty(propertySource, propertyName, { + writable: true, + enumerable: true, + configurable: true, + value: nextValue + }); + }; + if (typeof setProperty !== "undefined") { + return setProperty.call(target, [propertyName, nextValue], next); + } + return next(); + }; + handler.get = function(target, propertyName, receiver) { + const next = () => target[propertyName]; + const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next(); + if (typeof value === "function") { + return (...args) => { + const next2 = value.bind(target, ...args); + if (typeof methodCall !== "undefined") { + return methodCall.call(target, [propertyName, args], next2); + } + return next2(); + }; + } + return value; + }; + return handler; +} + +// src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +function isDomParserSupportedType(type) { + const supportedTypes = [ + "application/xhtml+xml", + "application/xml", + "image/svg+xml", + "text/html", + "text/xml" + ]; + return supportedTypes.some((supportedType) => { + return type.startsWith(supportedType); + }); +} + +// src/utils/parseJson.ts +function parseJson(data) { + try { + const json = JSON.parse(data); + return json; + } catch (_) { + return null; + } +} + +// src/interceptors/XMLHttpRequest/utils/createResponse.ts +function createResponse(request, body) { + const responseBodyOrNull = _chunkWZTE4PCOjs.FetchResponse.isResponseWithBody(request.status) ? body : null; + return new (0, _chunkWZTE4PCOjs.FetchResponse)(responseBodyOrNull, { + url: request.responseURL, + status: request.status, + statusText: request.statusText, + headers: createHeadersFromXMLHttpReqestHeaders( + request.getAllResponseHeaders() + ) + }); +} +function createHeadersFromXMLHttpReqestHeaders(headersString) { + const headers = new Headers(); + const lines = headersString.split(/[\r\n]+/); + for (const line of lines) { + if (line.trim() === "") { + continue; + } + const [name, ...parts] = line.split(": "); + const value = parts.join(": "); + headers.append(name, value); + } + return headers; +} + +// src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +async function getBodyByteLength(input) { + const explicitContentLength = input.headers.get("content-length"); + if (explicitContentLength != null && explicitContentLength !== "") { + return Number(explicitContentLength); + } + const buffer = await input.arrayBuffer(); + return buffer.byteLength; +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +var kIsRequestHandled = Symbol("kIsRequestHandled"); +var IS_NODE = _isnodeprocess.isNodeProcess.call(void 0, ); +var kFetchRequest = Symbol("kFetchRequest"); +var XMLHttpRequestController = class { + constructor(initialRequest, logger) { + this.initialRequest = initialRequest; + this.logger = logger; + this.method = "GET"; + this.url = null; + this[kIsRequestHandled] = false; + this.events = /* @__PURE__ */ new Map(); + this.uploadEvents = /* @__PURE__ */ new Map(); + this.requestId = _chunkWZTE4PCOjs.createRequestId.call(void 0, ); + this.requestHeaders = new Headers(); + this.responseBuffer = new Uint8Array(); + this.request = createProxy(initialRequest, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "ontimeout": { + const eventName = propertyName.slice( + 2 + ); + this.request.addEventListener(eventName, nextValue); + return invoke(); + } + default: { + return invoke(); + } + } + }, + methodCall: ([methodName, args], invoke) => { + var _a; + switch (methodName) { + case "open": { + const [method, url] = args; + if (typeof url === "undefined") { + this.method = "GET"; + this.url = toAbsoluteUrl(method); + } else { + this.method = method; + this.url = toAbsoluteUrl(url); + } + this.logger = this.logger.extend(`${this.method} ${this.url.href}`); + this.logger.info("open", this.method, this.url.href); + return invoke(); + } + case "addEventListener": { + const [eventName, listener] = args; + this.registerEvent(eventName, listener); + this.logger.info("addEventListener", eventName, listener); + return invoke(); + } + case "setRequestHeader": { + const [name, value] = args; + this.requestHeaders.set(name, value); + this.logger.info("setRequestHeader", name, value); + return invoke(); + } + case "send": { + const [body] = args; + this.request.addEventListener("load", () => { + if (typeof this.onResponse !== "undefined") { + const fetchResponse = createResponse( + this.request, + /** + * The `response` property is the right way to read + * the ambiguous response body, as the request's "responseType" may differ. + * @see https://xhr.spec.whatwg.org/#the-response-attribute + */ + this.request.response + ); + this.onResponse.call(this, { + response: fetchResponse, + isMockedResponse: this[kIsRequestHandled], + request: fetchRequest, + requestId: this.requestId + }); + } + }); + const requestBody = typeof body === "string" ? _chunkLK6DILFKjs.encodeBuffer.call(void 0, body) : body; + const fetchRequest = this.toFetchApiRequest(requestBody); + this[kFetchRequest] = fetchRequest.clone(); + const onceRequestSettled = ((_a = this.onRequest) == null ? void 0 : _a.call(this, { + request: fetchRequest, + requestId: this.requestId + })) || Promise.resolve(); + onceRequestSettled.finally(() => { + if (!this[kIsRequestHandled]) { + this.logger.info( + "request callback settled but request has not been handled (readystate %d), performing as-is...", + this.request.readyState + ); + if (IS_NODE) { + this.request.setRequestHeader( + _chunkWZTE4PCOjs.INTERNAL_REQUEST_ID_HEADER_NAME, + this.requestId + ); + } + return invoke(); + } + }); + break; + } + default: { + return invoke(); + } + } + } + }); + define( + this.request, + "upload", + createProxy(this.request.upload, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "onloadstart": + case "onprogress": + case "onaboart": + case "onerror": + case "onload": + case "ontimeout": + case "onloadend": { + const eventName = propertyName.slice( + 2 + ); + this.registerUploadEvent(eventName, nextValue); + } + } + return invoke(); + }, + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "addEventListener": { + const [eventName, listener] = args; + this.registerUploadEvent(eventName, listener); + this.logger.info("upload.addEventListener", eventName, listener); + return invoke(); + } + } + } + }) + ); + } + registerEvent(eventName, listener) { + const prevEvents = this.events.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.events.set(eventName, nextEvents); + this.logger.info('registered event "%s"', eventName, listener); + } + registerUploadEvent(eventName, listener) { + const prevEvents = this.uploadEvents.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.uploadEvents.set(eventName, nextEvents); + this.logger.info('registered upload event "%s"', eventName, listener); + } + /** + * Responds to the current request with the given + * Fetch API `Response` instance. + */ + async respondWith(response) { + this[kIsRequestHandled] = true; + if (this[kFetchRequest]) { + const totalRequestBodyLength = await getBodyByteLength( + this[kFetchRequest] + ); + this.trigger("loadstart", this.request.upload, { + loaded: 0, + total: totalRequestBodyLength + }); + this.trigger("progress", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("load", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("loadend", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + } + this.logger.info( + "responding with a mocked response: %d %s", + response.status, + response.statusText + ); + define(this.request, "status", response.status); + define(this.request, "statusText", response.statusText); + define(this.request, "responseURL", this.url.href); + this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, { + apply: (_, __, args) => { + this.logger.info("getResponseHeader", args[0]); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning null"); + return null; + } + const headerValue = response.headers.get(args[0]); + this.logger.info( + 'resolved response header "%s" to', + args[0], + headerValue + ); + return headerValue; + } + }); + this.request.getAllResponseHeaders = new Proxy( + this.request.getAllResponseHeaders, + { + apply: () => { + this.logger.info("getAllResponseHeaders"); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning empty string"); + return ""; + } + const headersList = Array.from(response.headers.entries()); + const allHeaders = headersList.map(([headerName, headerValue]) => { + return `${headerName}: ${headerValue}`; + }).join("\r\n"); + this.logger.info("resolved all response headers to", allHeaders); + return allHeaders; + } + } + ); + Object.defineProperties(this.request, { + response: { + enumerable: true, + configurable: false, + get: () => this.response + }, + responseText: { + enumerable: true, + configurable: false, + get: () => this.responseText + }, + responseXML: { + enumerable: true, + configurable: false, + get: () => this.responseXML + } + }); + const totalResponseBodyLength = await getBodyByteLength(response.clone()); + this.logger.info("calculated response body length", totalResponseBodyLength); + this.trigger("loadstart", this.request, { + loaded: 0, + total: totalResponseBodyLength + }); + this.setReadyState(this.request.HEADERS_RECEIVED); + this.setReadyState(this.request.LOADING); + const finalizeResponse = () => { + this.logger.info("finalizing the mocked response..."); + this.setReadyState(this.request.DONE); + this.trigger("load", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + this.trigger("loadend", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + }; + if (response.body) { + this.logger.info("mocked response has body, streaming..."); + const reader = response.body.getReader(); + const readNextResponseBodyChunk = async () => { + const { value, done } = await reader.read(); + if (done) { + this.logger.info("response body stream done!"); + finalizeResponse(); + return; + } + if (value) { + this.logger.info("read response body chunk:", value); + this.responseBuffer = concatArrayBuffer(this.responseBuffer, value); + this.trigger("progress", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + } + readNextResponseBodyChunk(); + }; + readNextResponseBodyChunk(); + } else { + finalizeResponse(); + } + } + responseBufferToText() { + return _chunkLK6DILFKjs.decodeBuffer.call(void 0, this.responseBuffer); + } + get response() { + this.logger.info( + "getResponse (responseType: %s)", + this.request.responseType + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + switch (this.request.responseType) { + case "json": { + const responseJson = parseJson(this.responseBufferToText()); + this.logger.info("resolved response JSON", responseJson); + return responseJson; + } + case "arraybuffer": { + const arrayBuffer = _chunkLK6DILFKjs.toArrayBuffer.call(void 0, this.responseBuffer); + this.logger.info("resolved response ArrayBuffer", arrayBuffer); + return arrayBuffer; + } + case "blob": { + const mimeType = this.request.getResponseHeader("Content-Type") || "text/plain"; + const responseBlob = new Blob([this.responseBufferToText()], { + type: mimeType + }); + this.logger.info( + "resolved response Blob (mime type: %s)", + responseBlob, + mimeType + ); + return responseBlob; + } + default: { + const responseText = this.responseBufferToText(); + this.logger.info( + 'resolving "%s" response type as text', + this.request.responseType, + responseText + ); + return responseText; + } + } + } + get responseText() { + _outvariant.invariant.call(void 0, + this.request.responseType === "" || this.request.responseType === "text", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.LOADING && this.request.readyState !== this.request.DONE) { + return ""; + } + const responseText = this.responseBufferToText(); + this.logger.info('getResponseText: "%s"', responseText); + return responseText; + } + get responseXML() { + _outvariant.invariant.call(void 0, + this.request.responseType === "" || this.request.responseType === "document", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + const contentType = this.request.getResponseHeader("Content-Type") || ""; + if (typeof DOMParser === "undefined") { + console.warn( + "Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly." + ); + return null; + } + if (isDomParserSupportedType(contentType)) { + return new DOMParser().parseFromString( + this.responseBufferToText(), + contentType + ); + } + return null; + } + errorWith(error) { + this[kIsRequestHandled] = true; + this.logger.info("responding with an error"); + this.setReadyState(this.request.DONE); + this.trigger("error", this.request); + this.trigger("loadend", this.request); + } + /** + * Transitions this request's `readyState` to the given one. + */ + setReadyState(nextReadyState) { + this.logger.info( + "setReadyState: %d -> %d", + this.request.readyState, + nextReadyState + ); + if (this.request.readyState === nextReadyState) { + this.logger.info("ready state identical, skipping transition..."); + return; + } + define(this.request, "readyState", nextReadyState); + this.logger.info("set readyState to: %d", nextReadyState); + if (nextReadyState !== this.request.UNSENT) { + this.logger.info('triggerring "readystatechange" event...'); + this.trigger("readystatechange", this.request); + } + } + /** + * Triggers given event on the `XMLHttpRequest` instance. + */ + trigger(eventName, target, options) { + const callback = target[`on${eventName}`]; + const event = createEvent(target, eventName, options); + this.logger.info('trigger "%s"', eventName, options || ""); + if (typeof callback === "function") { + this.logger.info('found a direct "%s" callback, calling...', eventName); + callback.call(target, event); + } + const events = target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events; + for (const [registeredEventName, listeners] of events) { + if (registeredEventName === eventName) { + this.logger.info( + 'found %d listener(s) for "%s" event, calling...', + listeners.length, + eventName + ); + listeners.forEach((listener) => listener.call(target, event)); + } + } + } + /** + * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance. + */ + toFetchApiRequest(body) { + this.logger.info("converting request to a Fetch API Request..."); + const resolvedBody = body instanceof Document ? body.documentElement.innerText : body; + const fetchRequest = new Request(this.url.href, { + method: this.method, + headers: this.requestHeaders, + /** + * @see https://xhr.spec.whatwg.org/#cross-origin-credentials + */ + credentials: this.request.withCredentials ? "include" : "same-origin", + body: ["GET", "HEAD"].includes(this.method.toUpperCase()) ? null : resolvedBody + }); + const proxyHeaders = createProxy(fetchRequest.headers, { + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "append": + case "set": { + const [headerName, headerValue] = args; + this.request.setRequestHeader(headerName, headerValue); + break; + } + case "delete": { + const [headerName] = args; + console.warn( + `XMLHttpRequest: Cannot remove a "${headerName}" header from the Fetch API representation of the "${fetchRequest.method} ${fetchRequest.url}" request. XMLHttpRequest headers cannot be removed.` + ); + break; + } + } + return invoke(); + } + }); + define(fetchRequest, "headers", proxyHeaders); + this.logger.info("converted request to a Fetch API Request!", fetchRequest); + return fetchRequest; + } +}; +kIsRequestHandled, kFetchRequest; +function toAbsoluteUrl(url) { + if (typeof location === "undefined") { + return new URL(url); + } + return new URL(url.toString(), location.href); +} +function define(target, property, value) { + Reflect.defineProperty(target, property, { + // Ensure writable properties to allow redefining readonly properties. + writable: true, + enumerable: true, + value + }); +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +function createXMLHttpRequestProxy({ + emitter, + logger +}) { + const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, { + construct(target, args, newTarget) { + logger.info("constructed new XMLHttpRequest"); + const originalRequest = Reflect.construct( + target, + args, + newTarget + ); + const prototypeDescriptors = Object.getOwnPropertyDescriptors( + target.prototype + ); + for (const propertyName in prototypeDescriptors) { + Reflect.defineProperty( + originalRequest, + propertyName, + prototypeDescriptors[propertyName] + ); + } + const xhrRequestController = new XMLHttpRequestController( + originalRequest, + logger + ); + xhrRequestController.onRequest = async function({ request, requestId }) { + const controller = new (0, _chunk6L3PFBGTjs.RequestController)(request); + this.logger.info("awaiting mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + emitter.listenerCount("request") + ); + const isRequestHandled = await _chunk6L3PFBGTjs.handleRequest.call(void 0, { + request, + requestId, + controller, + emitter, + onResponse: async (response) => { + await this.respondWith(response); + }, + onRequestError: () => { + this.errorWith(new TypeError("Network error")); + }, + onError: (error) => { + this.logger.info("request errored!", { error }); + if (error instanceof Error) { + this.errorWith(error); + } + } + }); + if (!isRequestHandled) { + this.logger.info( + "no mocked response received, performing request as-is..." + ); + } + }; + xhrRequestController.onResponse = async function({ + response, + isMockedResponse, + request, + requestId + }) { + this.logger.info( + 'emitting the "response" event for %s listener(s)...', + emitter.listenerCount("response") + ); + emitter.emit("response", { + response, + isMockedResponse, + request, + requestId + }); + }; + return xhrRequestController.request; + } + }); + return XMLHttpRequestProxy; +} + +// src/interceptors/XMLHttpRequest/index.ts +var _XMLHttpRequestInterceptor = class extends _chunkWZTE4PCOjs.Interceptor { + constructor() { + super(_XMLHttpRequestInterceptor.interceptorSymbol); + } + checkEnvironment() { + return _chunkPFGO5BSMjs.hasConfigurableGlobal.call(void 0, "XMLHttpRequest"); + } + setup() { + const logger = this.logger.extend("setup"); + logger.info('patching "XMLHttpRequest" module...'); + const PureXMLHttpRequest = globalThis.XMLHttpRequest; + _outvariant.invariant.call(void 0, + !PureXMLHttpRequest[_chunk73NOP3T5js.IS_PATCHED_MODULE], + 'Failed to patch the "XMLHttpRequest" module: already patched.' + ); + globalThis.XMLHttpRequest = createXMLHttpRequestProxy({ + emitter: this.emitter, + logger: this.logger + }); + logger.info( + 'native "XMLHttpRequest" module patched!', + globalThis.XMLHttpRequest.name + ); + Object.defineProperty(globalThis.XMLHttpRequest, _chunk73NOP3T5js.IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.XMLHttpRequest, _chunk73NOP3T5js.IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.XMLHttpRequest = PureXMLHttpRequest; + logger.info( + 'native "XMLHttpRequest" module restored!', + globalThis.XMLHttpRequest.name + ); + }); + } +}; +var XMLHttpRequestInterceptor = _XMLHttpRequestInterceptor; +XMLHttpRequestInterceptor.interceptorSymbol = Symbol("xhr"); + + + +exports.XMLHttpRequestInterceptor = XMLHttpRequestInterceptor; +//# sourceMappingURL=chunk-LCA4FKWY.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-LCA4FKWY.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-LCA4FKWY.js.map new file mode 100644 index 0000000000..dcd5d0b31b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-LCA4FKWY.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/XMLHttpRequest/index.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts","../../src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts","../../src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts","../../src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts","../../src/interceptors/XMLHttpRequest/utils/createEvent.ts","../../src/utils/findPropertySource.ts","../../src/utils/createProxy.ts","../../src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts","../../src/utils/parseJson.ts","../../src/interceptors/XMLHttpRequest/utils/createResponse.ts","../../src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts"],"names":["invariant","next"],"mappings":"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","sourcesContent":["import { invariant } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { createXMLHttpRequestProxy } from './XMLHttpRequestProxy'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\n\nexport type XMLHttpRequestEmitter = Emitter\n\nexport class XMLHttpRequestInterceptor extends Interceptor {\n static interceptorSymbol = Symbol('xhr')\n\n constructor() {\n super(XMLHttpRequestInterceptor.interceptorSymbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('XMLHttpRequest')\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('patching \"XMLHttpRequest\" module...')\n\n const PureXMLHttpRequest = globalThis.XMLHttpRequest\n\n invariant(\n !(PureXMLHttpRequest as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"XMLHttpRequest\" module: already patched.'\n )\n\n globalThis.XMLHttpRequest = createXMLHttpRequestProxy({\n emitter: this.emitter,\n logger: this.logger,\n })\n\n logger.info(\n 'native \"XMLHttpRequest\" module patched!',\n globalThis.XMLHttpRequest.name\n )\n\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.XMLHttpRequest = PureXMLHttpRequest\n logger.info(\n 'native \"XMLHttpRequest\" module restored!',\n globalThis.XMLHttpRequest.name\n )\n })\n }\n}\n","import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport type { Logger } from '@open-draft/logger'\nimport { concatArrayBuffer } from './utils/concatArrayBuffer'\nimport { createEvent } from './utils/createEvent'\nimport {\n decodeBuffer,\n encodeBuffer,\n toArrayBuffer,\n} from '../../utils/bufferUtils'\nimport { createProxy } from '../../utils/createProxy'\nimport { isDomParserSupportedType } from './utils/isDomParserSupportedType'\nimport { parseJson } from '../../utils/parseJson'\nimport { createResponse } from './utils/createResponse'\nimport { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'\nimport { createRequestId } from '../../createRequestId'\nimport { getBodyByteLength } from './utils/getBodyByteLength'\n\nconst kIsRequestHandled = Symbol('kIsRequestHandled')\nconst IS_NODE = isNodeProcess()\nconst kFetchRequest = Symbol('kFetchRequest')\n\n/**\n * An `XMLHttpRequest` instance controller that allows us\n * to handle any given request instance (e.g. responding to it).\n */\nexport class XMLHttpRequestController {\n public request: XMLHttpRequest\n public requestId: string\n public onRequest?: (\n this: XMLHttpRequestController,\n args: {\n request: Request\n requestId: string\n }\n ) => Promise\n public onResponse?: (\n this: XMLHttpRequestController,\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ) => void;\n\n [kIsRequestHandled]: boolean;\n [kFetchRequest]?: Request\n private method: string = 'GET'\n private url: URL = null as any\n private requestHeaders: Headers\n private responseBuffer: Uint8Array\n private events: Map>\n private uploadEvents: Map<\n keyof XMLHttpRequestEventTargetEventMap,\n Array\n >\n\n constructor(readonly initialRequest: XMLHttpRequest, public logger: Logger) {\n this[kIsRequestHandled] = false\n\n this.events = new Map()\n this.uploadEvents = new Map()\n this.requestId = createRequestId()\n this.requestHeaders = new Headers()\n this.responseBuffer = new Uint8Array()\n\n this.request = createProxy(initialRequest, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'ontimeout': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n /**\n * @note Proxy callbacks to event listeners because JSDOM has trouble\n * translating these properties to callbacks. It seemed to be operating\n * on events exclusively.\n */\n this.request.addEventListener(eventName, nextValue as any)\n\n return invoke()\n }\n\n default: {\n return invoke()\n }\n }\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'open': {\n const [method, url] = args as [string, string | undefined]\n\n if (typeof url === 'undefined') {\n this.method = 'GET'\n this.url = toAbsoluteUrl(method)\n } else {\n this.method = method\n this.url = toAbsoluteUrl(url)\n }\n\n this.logger = this.logger.extend(`${this.method} ${this.url.href}`)\n this.logger.info('open', this.method, this.url.href)\n\n return invoke()\n }\n\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n\n this.registerEvent(eventName, listener)\n this.logger.info('addEventListener', eventName, listener)\n\n return invoke()\n }\n\n case 'setRequestHeader': {\n const [name, value] = args as [string, string]\n this.requestHeaders.set(name, value)\n\n this.logger.info('setRequestHeader', name, value)\n\n return invoke()\n }\n\n case 'send': {\n const [body] = args as [\n body?: XMLHttpRequestBodyInit | Document | null\n ]\n\n this.request.addEventListener('load', () => {\n if (typeof this.onResponse !== 'undefined') {\n // Create a Fetch API Response representation of whichever\n // response this XMLHttpRequest received. Note those may\n // be either a mocked and the original response.\n const fetchResponse = createResponse(\n this.request,\n /**\n * The `response` property is the right way to read\n * the ambiguous response body, as the request's \"responseType\" may differ.\n * @see https://xhr.spec.whatwg.org/#the-response-attribute\n */\n this.request.response\n )\n\n // Notify the consumer about the response.\n this.onResponse.call(this, {\n response: fetchResponse,\n isMockedResponse: this[kIsRequestHandled],\n request: fetchRequest,\n requestId: this.requestId!,\n })\n }\n })\n\n const requestBody =\n typeof body === 'string' ? encodeBuffer(body) : body\n\n // Delegate request handling to the consumer.\n const fetchRequest = this.toFetchApiRequest(requestBody)\n this[kFetchRequest] = fetchRequest.clone()\n\n const onceRequestSettled =\n this.onRequest?.call(this, {\n request: fetchRequest,\n requestId: this.requestId!,\n }) || Promise.resolve()\n\n onceRequestSettled.finally(() => {\n // If the consumer didn't handle the request (called `.respondWith()`) perform it as-is.\n if (!this[kIsRequestHandled]) {\n this.logger.info(\n 'request callback settled but request has not been handled (readystate %d), performing as-is...',\n this.request.readyState\n )\n\n /**\n * @note Set the intercepted request ID on the original request in Node.js\n * so that if it triggers any other interceptors, they don't attempt\n * to process it once again.\n *\n * For instance, XMLHttpRequest is often implemented via \"http.ClientRequest\"\n * and we don't want for both XHR and ClientRequest interceptors to\n * handle the same request at the same time (e.g. emit the \"response\" event twice).\n */\n if (IS_NODE) {\n this.request.setRequestHeader(\n INTERNAL_REQUEST_ID_HEADER_NAME,\n this.requestId!\n )\n }\n\n return invoke()\n }\n })\n\n break\n }\n\n default: {\n return invoke()\n }\n }\n },\n })\n\n /**\n * Proxy the `.upload` property to gather the event listeners/callbacks.\n */\n define(\n this.request,\n 'upload',\n createProxy(this.request.upload, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'onloadstart':\n case 'onprogress':\n case 'onaboart':\n case 'onerror':\n case 'onload':\n case 'ontimeout':\n case 'onloadend': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n this.registerUploadEvent(eventName, nextValue as Function)\n }\n }\n\n return invoke()\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n this.registerUploadEvent(eventName, listener)\n this.logger.info('upload.addEventListener', eventName, listener)\n\n return invoke()\n }\n }\n },\n })\n )\n }\n\n private registerEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.events.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.events.set(eventName, nextEvents)\n\n this.logger.info('registered event \"%s\"', eventName, listener)\n }\n\n private registerUploadEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.uploadEvents.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.uploadEvents.set(eventName, nextEvents)\n\n this.logger.info('registered upload event \"%s\"', eventName, listener)\n }\n\n /**\n * Responds to the current request with the given\n * Fetch API `Response` instance.\n */\n public async respondWith(response: Response): Promise {\n /**\n * @note Since `XMLHttpRequestController` delegates the handling of the responses\n * to the \"load\" event listener that doesn't distinguish between the mocked and original\n * responses, mark the request that had a mocked response with a corresponding symbol.\n *\n * Mark this request as having a mocked response immediately since\n * calculating request/response total body length is asynchronous.\n */\n this[kIsRequestHandled] = true\n\n /**\n * Dispatch request upload events for requests with a body.\n * @see https://github.com/mswjs/interceptors/issues/573\n */\n if (this[kFetchRequest]) {\n const totalRequestBodyLength = await getBodyByteLength(\n this[kFetchRequest]\n )\n\n this.trigger('loadstart', this.request.upload, {\n loaded: 0,\n total: totalRequestBodyLength,\n })\n this.trigger('progress', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('load', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('loadend', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n }\n\n this.logger.info(\n 'responding with a mocked response: %d %s',\n response.status,\n response.statusText\n )\n\n define(this.request, 'status', response.status)\n define(this.request, 'statusText', response.statusText)\n define(this.request, 'responseURL', this.url.href)\n\n this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, {\n apply: (_, __, args: [name: string]) => {\n this.logger.info('getResponseHeader', args[0])\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning null')\n\n // Headers not received yet, nothing to return.\n return null\n }\n\n const headerValue = response.headers.get(args[0])\n this.logger.info(\n 'resolved response header \"%s\" to',\n args[0],\n headerValue\n )\n\n return headerValue\n },\n })\n\n this.request.getAllResponseHeaders = new Proxy(\n this.request.getAllResponseHeaders,\n {\n apply: () => {\n this.logger.info('getAllResponseHeaders')\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning empty string')\n\n // Headers not received yet, nothing to return.\n return ''\n }\n\n const headersList = Array.from(response.headers.entries())\n const allHeaders = headersList\n .map(([headerName, headerValue]) => {\n return `${headerName}: ${headerValue}`\n })\n .join('\\r\\n')\n\n this.logger.info('resolved all response headers to', allHeaders)\n\n return allHeaders\n },\n }\n )\n\n // Update the response getters to resolve against the mocked response.\n Object.defineProperties(this.request, {\n response: {\n enumerable: true,\n configurable: false,\n get: () => this.response,\n },\n responseText: {\n enumerable: true,\n configurable: false,\n get: () => this.responseText,\n },\n responseXML: {\n enumerable: true,\n configurable: false,\n get: () => this.responseXML,\n },\n })\n\n const totalResponseBodyLength = await getBodyByteLength(response.clone())\n\n this.logger.info('calculated response body length', totalResponseBodyLength)\n\n this.trigger('loadstart', this.request, {\n loaded: 0,\n total: totalResponseBodyLength,\n })\n\n this.setReadyState(this.request.HEADERS_RECEIVED)\n this.setReadyState(this.request.LOADING)\n\n const finalizeResponse = () => {\n this.logger.info('finalizing the mocked response...')\n\n this.setReadyState(this.request.DONE)\n\n this.trigger('load', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n\n this.trigger('loadend', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n if (response.body) {\n this.logger.info('mocked response has body, streaming...')\n\n const reader = response.body.getReader()\n\n const readNextResponseBodyChunk = async () => {\n const { value, done } = await reader.read()\n\n if (done) {\n this.logger.info('response body stream done!')\n finalizeResponse()\n return\n }\n\n if (value) {\n this.logger.info('read response body chunk:', value)\n this.responseBuffer = concatArrayBuffer(this.responseBuffer, value)\n\n this.trigger('progress', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n readNextResponseBodyChunk()\n }\n\n readNextResponseBodyChunk()\n } else {\n finalizeResponse()\n }\n }\n\n private responseBufferToText(): string {\n return decodeBuffer(this.responseBuffer)\n }\n\n get response(): unknown {\n this.logger.info(\n 'getResponse (responseType: %s)',\n this.request.responseType\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n switch (this.request.responseType) {\n case 'json': {\n const responseJson = parseJson(this.responseBufferToText())\n this.logger.info('resolved response JSON', responseJson)\n\n return responseJson\n }\n\n case 'arraybuffer': {\n const arrayBuffer = toArrayBuffer(this.responseBuffer)\n this.logger.info('resolved response ArrayBuffer', arrayBuffer)\n\n return arrayBuffer\n }\n\n case 'blob': {\n const mimeType =\n this.request.getResponseHeader('Content-Type') || 'text/plain'\n const responseBlob = new Blob([this.responseBufferToText()], {\n type: mimeType,\n })\n\n this.logger.info(\n 'resolved response Blob (mime type: %s)',\n responseBlob,\n mimeType\n )\n\n return responseBlob\n }\n\n default: {\n const responseText = this.responseBufferToText()\n this.logger.info(\n 'resolving \"%s\" response type as text',\n this.request.responseType,\n responseText\n )\n\n return responseText\n }\n }\n }\n\n get responseText(): string {\n /**\n * Throw when trying to read the response body as text when the\n * \"responseType\" doesn't expect text. This just respects the spec better.\n * @see https://xhr.spec.whatwg.org/#the-responsetext-attribute\n */\n invariant(\n this.request.responseType === '' || this.request.responseType === 'text',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (\n this.request.readyState !== this.request.LOADING &&\n this.request.readyState !== this.request.DONE\n ) {\n return ''\n }\n\n const responseText = this.responseBufferToText()\n this.logger.info('getResponseText: \"%s\"', responseText)\n\n return responseText\n }\n\n get responseXML(): Document | null {\n invariant(\n this.request.responseType === '' ||\n this.request.responseType === 'document',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n const contentType = this.request.getResponseHeader('Content-Type') || ''\n\n if (typeof DOMParser === 'undefined') {\n console.warn(\n 'Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly.'\n )\n return null\n }\n\n if (isDomParserSupportedType(contentType)) {\n return new DOMParser().parseFromString(\n this.responseBufferToText(),\n contentType\n )\n }\n\n return null\n }\n\n public errorWith(error?: Error): void {\n /**\n * @note Mark this request as handled even if it received a mock error.\n * This prevents the controller from trying to perform this request as-is.\n */\n this[kIsRequestHandled] = true\n this.logger.info('responding with an error')\n\n this.setReadyState(this.request.DONE)\n this.trigger('error', this.request)\n this.trigger('loadend', this.request)\n }\n\n /**\n * Transitions this request's `readyState` to the given one.\n */\n private setReadyState(nextReadyState: number): void {\n this.logger.info(\n 'setReadyState: %d -> %d',\n this.request.readyState,\n nextReadyState\n )\n\n if (this.request.readyState === nextReadyState) {\n this.logger.info('ready state identical, skipping transition...')\n return\n }\n\n define(this.request, 'readyState', nextReadyState)\n\n this.logger.info('set readyState to: %d', nextReadyState)\n\n if (nextReadyState !== this.request.UNSENT) {\n this.logger.info('triggerring \"readystatechange\" event...')\n\n this.trigger('readystatechange', this.request)\n }\n }\n\n /**\n * Triggers given event on the `XMLHttpRequest` instance.\n */\n private trigger<\n EventName extends keyof (XMLHttpRequestEventTargetEventMap & {\n readystatechange: ProgressEvent\n })\n >(\n eventName: EventName,\n target: XMLHttpRequest | XMLHttpRequestUpload,\n options?: ProgressEventInit\n ): void {\n const callback = (target as XMLHttpRequest)[`on${eventName}`]\n const event = createEvent(target, eventName, options)\n\n this.logger.info('trigger \"%s\"', eventName, options || '')\n\n // Invoke direct callbacks.\n if (typeof callback === 'function') {\n this.logger.info('found a direct \"%s\" callback, calling...', eventName)\n callback.call(target as XMLHttpRequest, event)\n }\n\n // Invoke event listeners.\n const events =\n target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events\n\n for (const [registeredEventName, listeners] of events) {\n if (registeredEventName === eventName) {\n this.logger.info(\n 'found %d listener(s) for \"%s\" event, calling...',\n listeners.length,\n eventName\n )\n\n listeners.forEach((listener) => listener.call(target, event))\n }\n }\n }\n\n /**\n * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance.\n */\n private toFetchApiRequest(\n body: XMLHttpRequestBodyInit | Document | null | undefined\n ): Request {\n this.logger.info('converting request to a Fetch API Request...')\n\n // If the `Document` is used as the body of this XMLHttpRequest,\n // set its inner text as the Fetch API Request body.\n const resolvedBody =\n body instanceof Document ? body.documentElement.innerText : body\n\n const fetchRequest = new Request(this.url.href, {\n method: this.method,\n headers: this.requestHeaders,\n /**\n * @see https://xhr.spec.whatwg.org/#cross-origin-credentials\n */\n credentials: this.request.withCredentials ? 'include' : 'same-origin',\n body: ['GET', 'HEAD'].includes(this.method.toUpperCase())\n ? null\n : resolvedBody,\n })\n\n const proxyHeaders = createProxy(fetchRequest.headers, {\n methodCall: ([methodName, args], invoke) => {\n // Forward the latest state of the internal request headers\n // because the interceptor might have modified them\n // without responding to the request.\n switch (methodName) {\n case 'append':\n case 'set': {\n const [headerName, headerValue] = args as [string, string]\n this.request.setRequestHeader(headerName, headerValue)\n break\n }\n\n case 'delete': {\n const [headerName] = args as [string]\n console.warn(\n `XMLHttpRequest: Cannot remove a \"${headerName}\" header from the Fetch API representation of the \"${fetchRequest.method} ${fetchRequest.url}\" request. XMLHttpRequest headers cannot be removed.`\n )\n break\n }\n }\n\n return invoke()\n },\n })\n define(fetchRequest, 'headers', proxyHeaders)\n\n this.logger.info('converted request to a Fetch API Request!', fetchRequest)\n\n return fetchRequest\n }\n}\n\nfunction toAbsoluteUrl(url: string | URL): URL {\n /**\n * @note XMLHttpRequest interceptor may run in environments\n * that implement XMLHttpRequest but don't implement \"location\"\n * (for example, React Native). If that's the case, return the\n * input URL as-is (nothing to be relative to).\n * @see https://github.com/mswjs/msw/issues/1777\n */\n if (typeof location === 'undefined') {\n return new URL(url)\n }\n\n return new URL(url.toString(), location.href)\n}\n\nfunction define(\n target: object,\n property: string | symbol,\n value: unknown\n): void {\n Reflect.defineProperty(target, property, {\n // Ensure writable properties to allow redefining readonly properties.\n writable: true,\n enumerable: true,\n value,\n })\n}\n","/**\n * Concatenate two `Uint8Array` buffers.\n */\nexport function concatArrayBuffer(\n left: Uint8Array,\n right: Uint8Array\n): Uint8Array {\n const result = new Uint8Array(left.byteLength + right.byteLength)\n result.set(left, 0)\n result.set(right, left.byteLength)\n return result\n}\n","export class EventPolyfill implements Event {\n readonly NONE = 0\n readonly CAPTURING_PHASE = 1\n readonly AT_TARGET = 2\n readonly BUBBLING_PHASE = 3\n\n public type: string = ''\n public srcElement: EventTarget | null = null\n public target: EventTarget | null\n public currentTarget: EventTarget | null = null\n public eventPhase: number = 0\n public timeStamp: number\n public isTrusted: boolean = true\n public composed: boolean = false\n public cancelable: boolean = true\n public defaultPrevented: boolean = false\n public bubbles: boolean = true\n public lengthComputable: boolean = true\n public loaded: number = 0\n public total: number = 0\n\n cancelBubble: boolean = false\n returnValue: boolean = true\n\n constructor(\n type: string,\n options?: { target: EventTarget; currentTarget: EventTarget }\n ) {\n this.type = type\n this.target = options?.target || null\n this.currentTarget = options?.currentTarget || null\n this.timeStamp = Date.now()\n }\n\n public composedPath(): EventTarget[] {\n return []\n }\n\n public initEvent(type: string, bubbles?: boolean, cancelable?: boolean) {\n this.type = type\n this.bubbles = !!bubbles\n this.cancelable = !!cancelable\n }\n\n public preventDefault() {\n this.defaultPrevented = true\n }\n\n public stopPropagation() {}\n public stopImmediatePropagation() {}\n}\n","import { EventPolyfill } from './EventPolyfill'\n\nexport class ProgressEventPolyfill extends EventPolyfill {\n readonly lengthComputable: boolean\n readonly composed: boolean\n readonly loaded: number\n readonly total: number\n\n constructor(type: string, init?: ProgressEventInit) {\n super(type)\n\n this.lengthComputable = init?.lengthComputable || false\n this.composed = init?.composed || false\n this.loaded = init?.loaded || 0\n this.total = init?.total || 0\n }\n}\n","import { EventPolyfill } from '../polyfills/EventPolyfill'\nimport { ProgressEventPolyfill } from '../polyfills/ProgressEventPolyfill'\n\nconst SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== 'undefined'\n\nexport function createEvent(\n target: XMLHttpRequest | XMLHttpRequestUpload,\n type: string,\n init?: ProgressEventInit\n): EventPolyfill | ProgressEvent {\n const progressEvents = [\n 'error',\n 'progress',\n 'loadstart',\n 'loadend',\n 'load',\n 'timeout',\n 'abort',\n ]\n\n /**\n * `ProgressEvent` is not supported in React Native.\n * @see https://github.com/mswjs/interceptors/issues/40\n */\n const ProgressEventClass = SUPPORTS_PROGRESS_EVENT\n ? ProgressEvent\n : ProgressEventPolyfill\n\n const event = progressEvents.includes(type)\n ? new ProgressEventClass(type, {\n lengthComputable: true,\n loaded: init?.loaded || 0,\n total: init?.total || 0,\n })\n : new EventPolyfill(type, {\n target,\n currentTarget: target,\n })\n\n return event\n}\n","/**\n * Returns the source object of the given property on the target object\n * (the target itself, any parent in its prototype, or null).\n */\nexport function findPropertySource(\n target: object,\n propertyName: string | symbol\n): object | null {\n if (!(propertyName in target)) {\n return null\n }\n\n const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName)\n if (hasProperty) {\n return target\n }\n\n const prototype = Reflect.getPrototypeOf(target)\n return prototype ? findPropertySource(prototype, propertyName) : null\n}\n","import { findPropertySource } from './findPropertySource'\n\nexport interface ProxyOptions> {\n constructorCall?(args: Array, next: NextFunction): Target\n\n methodCall?(\n this: Target,\n data: [methodName: F, args: Array],\n next: NextFunction\n ): void\n\n setProperty?(\n data: [propertyName: string | symbol, nextValue: unknown],\n next: NextFunction\n ): boolean\n\n getProperty?(\n data: [propertyName: string | symbol, receiver: Target],\n next: NextFunction\n ): void\n}\n\nexport type NextFunction = () => ReturnType\n\nexport function createProxy(\n target: Target,\n options: ProxyOptions\n): Target {\n const proxy = new Proxy(target, optionsToProxyHandler(options))\n\n return proxy\n}\n\nfunction optionsToProxyHandler>(\n options: ProxyOptions\n): ProxyHandler {\n const { constructorCall, methodCall, getProperty, setProperty } = options\n const handler: ProxyHandler = {}\n\n if (typeof constructorCall !== 'undefined') {\n handler.construct = function (target, args, newTarget) {\n const next = Reflect.construct.bind(null, target as any, args, newTarget)\n return constructorCall.call(newTarget, args, next)\n }\n }\n\n handler.set = function (target, propertyName, nextValue) {\n const next = () => {\n const propertySource = findPropertySource(target, propertyName) || target\n const ownDescriptors = Reflect.getOwnPropertyDescriptor(\n propertySource,\n propertyName\n )\n\n // Respect any custom setters present for this property.\n if (typeof ownDescriptors?.set !== 'undefined') {\n ownDescriptors.set.apply(target, [nextValue])\n return true\n }\n\n // Otherwise, set the property on the source.\n return Reflect.defineProperty(propertySource, propertyName, {\n writable: true,\n enumerable: true,\n configurable: true,\n value: nextValue,\n })\n }\n\n if (typeof setProperty !== 'undefined') {\n return setProperty.call(target, [propertyName, nextValue], next)\n }\n\n return next()\n }\n\n handler.get = function (target, propertyName, receiver) {\n /**\n * @note Using `Reflect.get()` here causes \"TypeError: Illegal invocation\".\n */\n const next = () => target[propertyName as any]\n\n const value =\n typeof getProperty !== 'undefined'\n ? getProperty.call(target, [propertyName, receiver], next)\n : next()\n\n if (typeof value === 'function') {\n return (...args: Array) => {\n const next = value.bind(target, ...args)\n\n if (typeof methodCall !== 'undefined') {\n return methodCall.call(target, [propertyName as any, args], next)\n }\n\n return next()\n }\n }\n\n return value\n }\n\n return handler\n}\n","export function isDomParserSupportedType(\n type: string\n): type is DOMParserSupportedType {\n const supportedTypes: Array = [\n 'application/xhtml+xml',\n 'application/xml',\n 'image/svg+xml',\n 'text/html',\n 'text/xml',\n ]\n return supportedTypes.some((supportedType) => {\n return type.startsWith(supportedType)\n })\n}\n","/**\n * Parses a given string into JSON.\n * Gracefully handles invalid JSON by returning `null`.\n */\nexport function parseJson(data: string): Record | null {\n try {\n const json = JSON.parse(data)\n return json\n } catch (_) {\n return null\n }\n}\n","import { FetchResponse } from '../../../utils/fetchUtils'\n\n/**\n * Creates a Fetch API `Response` instance from the given\n * `XMLHttpRequest` instance and a response body.\n */\nexport function createResponse(\n request: XMLHttpRequest,\n body: BodyInit | null\n): Response {\n /**\n * Handle XMLHttpRequest responses that must have null as the\n * response body when represented using Fetch API Response.\n * XMLHttpRequest response will always have an empty string\n * as the \"request.response\" in those cases, resulting in an error\n * when constructing a Response instance.\n * @see https://github.com/mswjs/interceptors/issues/379\n */\n const responseBodyOrNull = FetchResponse.isResponseWithBody(request.status)\n ? body\n : null\n\n return new FetchResponse(responseBodyOrNull, {\n url: request.responseURL,\n status: request.status,\n statusText: request.statusText,\n headers: createHeadersFromXMLHttpReqestHeaders(\n request.getAllResponseHeaders()\n ),\n })\n}\n\nfunction createHeadersFromXMLHttpReqestHeaders(headersString: string): Headers {\n const headers = new Headers()\n\n const lines = headersString.split(/[\\r\\n]+/)\n for (const line of lines) {\n if (line.trim() === '') {\n continue\n }\n\n const [name, ...parts] = line.split(': ')\n const value = parts.join(': ')\n\n headers.append(name, value)\n }\n\n return headers\n}\n","/**\n * Return a total byte length of the given request/response body.\n * If the `Content-Length` header is present, it will be used as the byte length.\n */\nexport async function getBodyByteLength(\n input: Request | Response\n): Promise {\n const explicitContentLength = input.headers.get('content-length')\n\n if (explicitContentLength != null && explicitContentLength !== '') {\n return Number(explicitContentLength)\n }\n\n const buffer = await input.arrayBuffer()\n return buffer.byteLength\n}\n","import type { Logger } from '@open-draft/logger'\nimport { XMLHttpRequestEmitter } from '.'\nimport { RequestController } from '../../RequestController'\nimport { XMLHttpRequestController } from './XMLHttpRequestController'\nimport { handleRequest } from '../../utils/handleRequest'\n\nexport interface XMLHttpRequestProxyOptions {\n emitter: XMLHttpRequestEmitter\n logger: Logger\n}\n\n/**\n * Create a proxied `XMLHttpRequest` class.\n * The proxied class establishes spies on certain methods,\n * allowing us to intercept requests and respond to them.\n */\nexport function createXMLHttpRequestProxy({\n emitter,\n logger,\n}: XMLHttpRequestProxyOptions) {\n const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {\n construct(target, args, newTarget) {\n logger.info('constructed new XMLHttpRequest')\n\n const originalRequest = Reflect.construct(\n target,\n args,\n newTarget\n ) as XMLHttpRequest\n\n /**\n * @note Forward prototype descriptors onto the proxied object.\n * XMLHttpRequest is implemented in JSDOM in a way that assigns\n * a bunch of descriptors, like \"set responseType()\" on the prototype.\n * With this propagation, we make sure that those descriptors trigger\n * when the user operates with the proxied request instance.\n */\n const prototypeDescriptors = Object.getOwnPropertyDescriptors(\n target.prototype\n )\n for (const propertyName in prototypeDescriptors) {\n Reflect.defineProperty(\n originalRequest,\n propertyName,\n prototypeDescriptors[propertyName]\n )\n }\n\n const xhrRequestController = new XMLHttpRequestController(\n originalRequest,\n logger\n )\n\n xhrRequestController.onRequest = async function ({ request, requestId }) {\n const controller = new RequestController(request)\n\n this.logger.info('awaiting mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n controller,\n emitter,\n onResponse: async (response) => {\n await this.respondWith(response)\n },\n onRequestError: () => {\n this.errorWith(new TypeError('Network error'))\n },\n onError: (error) => {\n this.logger.info('request errored!', { error })\n\n if (error instanceof Error) {\n this.errorWith(error)\n }\n },\n })\n\n if (!isRequestHandled) {\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n }\n }\n\n xhrRequestController.onResponse = async function ({\n response,\n isMockedResponse,\n request,\n requestId,\n }) {\n this.logger.info(\n 'emitting the \"response\" event for %s listener(s)...',\n emitter.listenerCount('response')\n )\n\n emitter.emit('response', {\n response,\n isMockedResponse,\n request,\n requestId,\n })\n }\n\n // Return the proxied request from the controller\n // so that the controller can react to the consumer's interactions\n // with this request (opening/sending/etc).\n return xhrRequestController.request\n },\n })\n\n return XMLHttpRequestProxy\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-LEA3MUU3.js b/node_modules/@mswjs/interceptors/lib/node/chunk-LEA3MUU3.js new file mode 100644 index 0000000000..f543561639 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-LEA3MUU3.js @@ -0,0 +1,310 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _chunkPFGO5BSMjs = require('./chunk-PFGO5BSM.js'); + + +var _chunk73NOP3T5js = require('./chunk-73NOP3T5.js'); + + + + +var _chunk6L3PFBGTjs = require('./chunk-6L3PFBGT.js'); + + + + +var _chunkWZTE4PCOjs = require('./chunk-WZTE4PCO.js'); + +// src/interceptors/fetch/index.ts +var _outvariant = require('outvariant'); +var _deferredpromise = require('@open-draft/deferred-promise'); + +// src/utils/canParseUrl.ts +function canParseUrl(url) { + try { + new URL(url); + return true; + } catch (_error) { + return false; + } +} + +// src/interceptors/fetch/utils/createNetworkError.ts +function createNetworkError(cause) { + return Object.assign(new TypeError("Failed to fetch"), { + cause + }); +} + +// src/interceptors/fetch/utils/followRedirect.ts +var REQUEST_BODY_HEADERS = [ + "content-encoding", + "content-language", + "content-location", + "content-type", + "content-length" +]; +var kRedirectCount = Symbol("kRedirectCount"); +async function followFetchRedirect(request, response) { + if (response.status !== 303 && request.body != null) { + return Promise.reject(createNetworkError()); + } + const requestUrl = new URL(request.url); + let locationUrl; + try { + locationUrl = new URL(response.headers.get("location"), request.url); + } catch (error) { + return Promise.reject(createNetworkError(error)); + } + if (!(locationUrl.protocol === "http:" || locationUrl.protocol === "https:")) { + return Promise.reject( + createNetworkError("URL scheme must be a HTTP(S) scheme") + ); + } + if (Reflect.get(request, kRedirectCount) > 20) { + return Promise.reject(createNetworkError("redirect count exceeded")); + } + Object.defineProperty(request, kRedirectCount, { + value: (Reflect.get(request, kRedirectCount) || 0) + 1 + }); + if (request.mode === "cors" && (locationUrl.username || locationUrl.password) && !sameOrigin(requestUrl, locationUrl)) { + return Promise.reject( + createNetworkError('cross origin not allowed for request mode "cors"') + ); + } + const requestInit = {}; + if ([301, 302].includes(response.status) && request.method === "POST" || response.status === 303 && !["HEAD", "GET"].includes(request.method)) { + requestInit.method = "GET"; + requestInit.body = null; + REQUEST_BODY_HEADERS.forEach((headerName) => { + request.headers.delete(headerName); + }); + } + if (!sameOrigin(requestUrl, locationUrl)) { + request.headers.delete("authorization"); + request.headers.delete("proxy-authorization"); + request.headers.delete("cookie"); + request.headers.delete("host"); + } + requestInit.headers = request.headers; + return fetch(new Request(locationUrl, requestInit)); +} +function sameOrigin(left, right) { + if (left.origin === right.origin && left.origin === "null") { + return true; + } + if (left.protocol === right.protocol && left.hostname === right.hostname && left.port === right.port) { + return true; + } + return false; +} + +// src/interceptors/fetch/utils/brotli-decompress.ts +var _zlib = require('zlib'); var _zlib2 = _interopRequireDefault(_zlib); +var BrotliDecompressionStream = class extends TransformStream { + constructor() { + const decompress = _zlib2.default.createBrotliDecompress({ + flush: _zlib2.default.constants.BROTLI_OPERATION_FLUSH, + finishFlush: _zlib2.default.constants.BROTLI_OPERATION_FLUSH + }); + super({ + async transform(chunk, controller) { + const buffer = Buffer.from(chunk); + const decompressed = await new Promise((resolve, reject) => { + decompress.write(buffer, (error) => { + if (error) + reject(error); + }); + decompress.flush(); + decompress.once("data", (data) => resolve(data)); + decompress.once("error", (error) => reject(error)); + decompress.once("end", () => controller.terminate()); + }).catch((error) => { + controller.error(error); + }); + controller.enqueue(decompressed); + } + }); + } +}; + +// src/interceptors/fetch/utils/decompression.ts +var PipelineStream = class extends TransformStream { + constructor(transformStreams, ...strategies) { + super({}, ...strategies); + const readable = [super.readable, ...transformStreams].reduce( + (readable2, transform) => readable2.pipeThrough(transform) + ); + Object.defineProperty(this, "readable", { + get() { + return readable; + } + }); + } +}; +function parseContentEncoding(contentEncoding) { + return contentEncoding.toLowerCase().split(",").map((coding) => coding.trim()); +} +function createDecompressionStream(contentEncoding) { + if (contentEncoding === "") { + return null; + } + const codings = parseContentEncoding(contentEncoding); + if (codings.length === 0) { + return null; + } + const transformers = codings.reduceRight( + (transformers2, coding) => { + if (coding === "gzip" || coding === "x-gzip") { + return transformers2.concat(new DecompressionStream("gzip")); + } else if (coding === "deflate") { + return transformers2.concat(new DecompressionStream("deflate")); + } else if (coding === "br") { + return transformers2.concat(new BrotliDecompressionStream()); + } else { + transformers2.length = 0; + } + return transformers2; + }, + [] + ); + return new PipelineStream(transformers); +} +function decompressResponse(response) { + if (response.body === null) { + return null; + } + const decompressionStream = createDecompressionStream( + response.headers.get("content-encoding") || "" + ); + if (!decompressionStream) { + return null; + } + response.body.pipeTo(decompressionStream.writable); + return decompressionStream.readable; +} + +// src/interceptors/fetch/index.ts +var _FetchInterceptor = class extends _chunkWZTE4PCOjs.Interceptor { + constructor() { + super(_FetchInterceptor.symbol); + } + checkEnvironment() { + return _chunkPFGO5BSMjs.hasConfigurableGlobal.call(void 0, "fetch"); + } + async setup() { + const pureFetch = globalThis.fetch; + _outvariant.invariant.call(void 0, + !pureFetch[_chunk73NOP3T5js.IS_PATCHED_MODULE], + 'Failed to patch the "fetch" module: already patched.' + ); + globalThis.fetch = async (input, init) => { + const requestId = _chunkWZTE4PCOjs.createRequestId.call(void 0, ); + const resolvedInput = typeof input === "string" && typeof location !== "undefined" && !canParseUrl(input) ? new URL(input, location.origin) : input; + const request = new Request(resolvedInput, init); + const responsePromise = new (0, _deferredpromise.DeferredPromise)(); + const controller = new (0, _chunk6L3PFBGTjs.RequestController)(request); + this.logger.info("[%s] %s", request.method, request.url); + this.logger.info("awaiting for the mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + this.emitter.listenerCount("request") + ); + const isRequestHandled = await _chunk6L3PFBGTjs.handleRequest.call(void 0, { + request, + requestId, + emitter: this.emitter, + controller, + onResponse: async (rawResponse) => { + this.logger.info("received mocked response!", { + rawResponse + }); + const decompressedStream = decompressResponse(rawResponse); + const response = decompressedStream === null ? rawResponse : new (0, _chunkWZTE4PCOjs.FetchResponse)(decompressedStream, rawResponse); + _chunkWZTE4PCOjs.FetchResponse.setUrl(request.url, response); + if (_chunkWZTE4PCOjs.FetchResponse.isRedirectResponse(response.status)) { + if (request.redirect === "error") { + responsePromise.reject(createNetworkError("unexpected redirect")); + return; + } + if (request.redirect === "follow") { + followFetchRedirect(request, response).then( + (response2) => { + responsePromise.resolve(response2); + }, + (reason) => { + responsePromise.reject(reason); + } + ); + return; + } + } + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + await _chunk6L3PFBGTjs.emitAsync.call(void 0, this.emitter, "response", { + // Clone the mocked response for the "response" event listener. + // This way, the listener can read the response and not lock its body + // for the actual fetch consumer. + response: response.clone(), + isMockedResponse: true, + request, + requestId + }); + } + responsePromise.resolve(response); + }, + onRequestError: (response) => { + this.logger.info("request has errored!", { response }); + responsePromise.reject(createNetworkError(response)); + }, + onError: (error) => { + this.logger.info("request has been aborted!", { error }); + responsePromise.reject(error); + } + }); + if (isRequestHandled) { + this.logger.info("request has been handled, returning mock promise..."); + return responsePromise; + } + this.logger.info( + "no mocked response received, performing request as-is..." + ); + return pureFetch(request).then(async (response) => { + this.logger.info("original fetch performed", response); + if (this.emitter.listenerCount("response") > 0) { + this.logger.info('emitting the "response" event...'); + const responseClone = response.clone(); + await _chunk6L3PFBGTjs.emitAsync.call(void 0, this.emitter, "response", { + response: responseClone, + isMockedResponse: false, + request, + requestId + }); + } + return response; + }); + }; + Object.defineProperty(globalThis.fetch, _chunk73NOP3T5js.IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.fetch, _chunk73NOP3T5js.IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.fetch = pureFetch; + this.logger.info( + 'restored native "globalThis.fetch"!', + globalThis.fetch.name + ); + }); + } +}; +var FetchInterceptor = _FetchInterceptor; +FetchInterceptor.symbol = Symbol("fetch"); + + + +exports.FetchInterceptor = FetchInterceptor; +//# sourceMappingURL=chunk-LEA3MUU3.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-LEA3MUU3.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-LEA3MUU3.js.map new file mode 100644 index 0000000000..1864a527fa --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-LEA3MUU3.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/fetch/index.ts","../../src/utils/canParseUrl.ts","../../src/interceptors/fetch/utils/createNetworkError.ts","../../src/interceptors/fetch/utils/followRedirect.ts","../../src/interceptors/fetch/utils/brotli-decompress.ts","../../src/interceptors/fetch/utils/decompression.ts"],"names":["readable","transformers","response"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;;;ACIzB,SAAS,YAAY,KAAsB;AAChD,MAAI;AACF,QAAI,IAAI,GAAG;AACX,WAAO;AAAA,EACT,SAAS,QAAP;AACA,WAAO;AAAA,EACT;AACF;;;ACZO,SAAS,mBAAmB,OAAiB;AAClD,SAAO,OAAO,OAAO,IAAI,UAAU,iBAAiB,GAAG;AAAA,IACrD;AAAA,EACF,CAAC;AACH;;;ACFA,IAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,OAAO,gBAAgB;AAK9C,eAAsB,oBACpB,SACA,UACmB;AACnB,MAAI,SAAS,WAAW,OAAO,QAAQ,QAAQ,MAAM;AACnD,WAAO,QAAQ,OAAO,mBAAmB,CAAC;AAAA,EAC5C;AAEA,QAAM,aAAa,IAAI,IAAI,QAAQ,GAAG;AAEtC,MAAI;AACJ,MAAI;AAEF,kBAAc,IAAI,IAAI,SAAS,QAAQ,IAAI,UAAU,GAAI,QAAQ,GAAG;AAAA,EACtE,SAAS,OAAP;AACA,WAAO,QAAQ,OAAO,mBAAmB,KAAK,CAAC;AAAA,EACjD;AAEA,MACE,EAAE,YAAY,aAAa,WAAW,YAAY,aAAa,WAC/D;AACA,WAAO,QAAQ;AAAA,MACb,mBAAmB,qCAAqC;AAAA,IAC1D;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,SAAS,cAAc,IAAI,IAAI;AAC7C,WAAO,QAAQ,OAAO,mBAAmB,yBAAyB,CAAC;AAAA,EACrE;AAEA,SAAO,eAAe,SAAS,gBAAgB;AAAA,IAC7C,QAAQ,QAAQ,IAAI,SAAS,cAAc,KAAK,KAAK;AAAA,EACvD,CAAC;AAED,MACE,QAAQ,SAAS,WAChB,YAAY,YAAY,YAAY,aACrC,CAAC,WAAW,YAAY,WAAW,GACnC;AACA,WAAO,QAAQ;AAAA,MACb,mBAAmB,kDAAkD;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,cAA2B,CAAC;AAElC,MACG,CAAC,KAAK,GAAG,EAAE,SAAS,SAAS,MAAM,KAAK,QAAQ,WAAW,UAC3D,SAAS,WAAW,OAAO,CAAC,CAAC,QAAQ,KAAK,EAAE,SAAS,QAAQ,MAAM,GACpE;AACA,gBAAY,SAAS;AACrB,gBAAY,OAAO;AAEnB,yBAAqB,QAAQ,CAAC,eAAe;AAC3C,cAAQ,QAAQ,OAAO,UAAU;AAAA,IACnC,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,WAAW,YAAY,WAAW,GAAG;AACxC,YAAQ,QAAQ,OAAO,eAAe;AACtC,YAAQ,QAAQ,OAAO,qBAAqB;AAC5C,YAAQ,QAAQ,OAAO,QAAQ;AAC/B,YAAQ,QAAQ,OAAO,MAAM;AAAA,EAC/B;AAQA,cAAY,UAAU,QAAQ;AAC9B,SAAO,MAAM,IAAI,QAAQ,aAAa,WAAW,CAAC;AACpD;AAKA,SAAS,WAAW,MAAW,OAAqB;AAClD,MAAI,KAAK,WAAW,MAAM,UAAU,KAAK,WAAW,QAAQ;AAC1D,WAAO;AAAA,EACT;AAEA,MACE,KAAK,aAAa,MAAM,YACxB,KAAK,aAAa,MAAM,YACxB,KAAK,SAAS,MAAM,MACpB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;AC3GA,OAAO,UAAU;AAEV,IAAM,4BAAN,cAAwC,gBAAgB;AAAA,EAC7D,cAAc;AACZ,UAAM,aAAa,KAAK,uBAAuB;AAAA,MAC7C,OAAO,KAAK,UAAU;AAAA,MACtB,aAAa,KAAK,UAAU;AAAA,IAC9B,CAAC;AAED,UAAM;AAAA,MACJ,MAAM,UAAU,OAAO,YAAY;AACjC,cAAM,SAAS,OAAO,KAAK,KAAK;AAEhC,cAAM,eAAe,MAAM,IAAI,QAAgB,CAAC,SAAS,WAAW;AAClE,qBAAW,MAAM,QAAQ,CAAC,UAAU;AAClC,gBAAI;AAAO,qBAAO,KAAK;AAAA,UACzB,CAAC;AAED,qBAAW,MAAM;AACjB,qBAAW,KAAK,QAAQ,CAAC,SAAS,QAAQ,IAAI,CAAC;AAC/C,qBAAW,KAAK,SAAS,CAAC,UAAU,OAAO,KAAK,CAAC;AACjD,qBAAW,KAAK,OAAO,MAAM,WAAW,UAAU,CAAC;AAAA,QACrD,CAAC,EAAE,MAAM,CAAC,UAAU;AAClB,qBAAW,MAAM,KAAK;AAAA,QACxB,CAAC;AAED,mBAAW,QAAQ,YAAY;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACzBA,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EAC3C,YACE,qBACG,YACH;AACA,UAAM,CAAC,GAAG,GAAG,UAAU;AAEvB,UAAM,WAAW,CAAC,MAAM,UAAiB,GAAG,gBAAgB,EAAE;AAAA,MAC5D,CAACA,WAAU,cAAcA,UAAS,YAAY,SAAS;AAAA,IACzD;AAEA,WAAO,eAAe,MAAM,YAAY;AAAA,MACtC,MAAM;AACJ,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,SAAS,qBAAqB,iBAAwC;AAC3E,SAAO,gBACJ,YAAY,EACZ,MAAM,GAAG,EACT,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC;AAClC;AAEA,SAAS,0BACP,iBACwB;AACxB,MAAI,oBAAoB,IAAI;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,qBAAqB,eAAe;AAEpD,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,QAAQ;AAAA,IAC3B,CAACC,eAAc,WAAW;AACxB,UAAI,WAAW,UAAU,WAAW,UAAU;AAC5C,eAAOA,cAAa,OAAO,IAAI,oBAAoB,MAAM,CAAC;AAAA,MAC5D,WAAW,WAAW,WAAW;AAC/B,eAAOA,cAAa,OAAO,IAAI,oBAAoB,SAAS,CAAC;AAAA,MAC/D,WAAW,WAAW,MAAM;AAC1B,eAAOA,cAAa,OAAO,IAAI,0BAA0B,CAAC;AAAA,MAC5D,OAAO;AACL,QAAAA,cAAa,SAAS;AAAA,MACxB;AAEA,aAAOA;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,eAAe,YAAY;AACxC;AAEO,SAAS,mBACd,UAC4B;AAC5B,MAAI,SAAS,SAAS,MAAM;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,sBAAsB;AAAA,IAC1B,SAAS,QAAQ,IAAI,kBAAkB,KAAK;AAAA,EAC9C;AAEA,MAAI,CAAC,qBAAqB;AACxB,WAAO;AAAA,EACT;AAKA,WAAS,KAAK,OAAO,oBAAoB,QAAQ;AACjD,SAAO,oBAAoB;AAC7B;;;ALrEO,IAAM,oBAAN,cAA+B,YAAiC;AAAA,EAGrE,cAAc;AACZ,UAAM,kBAAiB,MAAM;AAAA,EAC/B;AAAA,EAEU,mBAAmB;AAC3B,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAAA,EAEA,MAAgB,QAAQ;AACtB,UAAM,YAAY,WAAW;AAE7B;AAAA,MACE,CAAE,UAAkB,iBAAiB;AAAA,MACrC;AAAA,IACF;AAEA,eAAW,QAAQ,OAAO,OAAO,SAAS;AACxC,YAAM,YAAY,gBAAgB;AAQlC,YAAM,gBACJ,OAAO,UAAU,YACjB,OAAO,aAAa,eACpB,CAAC,YAAY,KAAK,IACd,IAAI,IAAI,OAAO,SAAS,MAAM,IAC9B;AAEN,YAAM,UAAU,IAAI,QAAQ,eAAe,IAAI;AAC/C,YAAM,kBAAkB,IAAI,gBAA0B;AACtD,YAAM,aAAa,IAAI,kBAAkB,OAAO;AAEhD,WAAK,OAAO,KAAK,WAAW,QAAQ,QAAQ,QAAQ,GAAG;AACvD,WAAK,OAAO,KAAK,qCAAqC;AAEtD,WAAK,OAAO;AAAA,QACV;AAAA,QACA,KAAK,QAAQ,cAAc,SAAS;AAAA,MACtC;AAEA,YAAM,mBAAmB,MAAM,cAAc;AAAA,QAC3C;AAAA,QACA;AAAA,QACA,SAAS,KAAK;AAAA,QACd;AAAA,QACA,YAAY,OAAO,gBAAgB;AACjC,eAAK,OAAO,KAAK,6BAA6B;AAAA,YAC5C;AAAA,UACF,CAAC;AAGD,gBAAM,qBAAqB,mBAAmB,WAAW;AACzD,gBAAM,WACJ,uBAAuB,OACnB,cACA,IAAI,cAAc,oBAAoB,WAAW;AAEvD,wBAAc,OAAO,QAAQ,KAAK,QAAQ;AAQ1C,cAAI,cAAc,mBAAmB,SAAS,MAAM,GAAG;AAGrD,gBAAI,QAAQ,aAAa,SAAS;AAChC,8BAAgB,OAAO,mBAAmB,qBAAqB,CAAC;AAChE;AAAA,YACF;AAEA,gBAAI,QAAQ,aAAa,UAAU;AACjC,kCAAoB,SAAS,QAAQ,EAAE;AAAA,gBACrC,CAACC,cAAa;AACZ,kCAAgB,QAAQA,SAAQ;AAAA,gBAClC;AAAA,gBACA,CAAC,WAAW;AACV,kCAAgB,OAAO,MAAM;AAAA,gBAC/B;AAAA,cACF;AACA;AAAA,YACF;AAAA,UACF;AAEA,cAAI,KAAK,QAAQ,cAAc,UAAU,IAAI,GAAG;AAC9C,iBAAK,OAAO,KAAK,kCAAkC;AAKnD,kBAAM,UAAU,KAAK,SAAS,YAAY;AAAA;AAAA;AAAA;AAAA,cAIxC,UAAU,SAAS,MAAM;AAAA,cACzB,kBAAkB;AAAA,cAClB;AAAA,cACA;AAAA,YACF,CAAC;AAAA,UACH;AAEA,0BAAgB,QAAQ,QAAQ;AAAA,QAClC;AAAA,QACA,gBAAgB,CAAC,aAAa;AAC5B,eAAK,OAAO,KAAK,wBAAwB,EAAE,SAAS,CAAC;AACrD,0BAAgB,OAAO,mBAAmB,QAAQ,CAAC;AAAA,QACrD;AAAA,QACA,SAAS,CAAC,UAAU;AAClB,eAAK,OAAO,KAAK,6BAA6B,EAAE,MAAM,CAAC;AACvD,0BAAgB,OAAO,KAAK;AAAA,QAC9B;AAAA,MACF,CAAC;AAED,UAAI,kBAAkB;AACpB,aAAK,OAAO,KAAK,qDAAqD;AACtE,eAAO;AAAA,MACT;AAEA,WAAK,OAAO;AAAA,QACV;AAAA,MACF;AAEA,aAAO,UAAU,OAAO,EAAE,KAAK,OAAO,aAAa;AACjD,aAAK,OAAO,KAAK,4BAA4B,QAAQ;AAErD,YAAI,KAAK,QAAQ,cAAc,UAAU,IAAI,GAAG;AAC9C,eAAK,OAAO,KAAK,kCAAkC;AAEnD,gBAAM,gBAAgB,SAAS,MAAM;AAErC,gBAAM,UAAU,KAAK,SAAS,YAAY;AAAA,YACxC,UAAU;AAAA,YACV,kBAAkB;AAAA,YAClB;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO,eAAe,WAAW,OAAO,mBAAmB;AAAA,MACzD,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,OAAO;AAAA,IACT,CAAC;AAED,SAAK,cAAc,KAAK,MAAM;AAC5B,aAAO,eAAe,WAAW,OAAO,mBAAmB;AAAA,QACzD,OAAO;AAAA,MACT,CAAC;AAED,iBAAW,QAAQ;AAEnB,WAAK,OAAO;AAAA,QACV;AAAA,QACA,WAAW,MAAM;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA1KO,IAAM,mBAAN;AAAM,iBACJ,SAAS,OAAO,OAAO","sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { RequestController } from '../../RequestController'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { handleRequest } from '../../utils/handleRequest'\nimport { canParseUrl } from '../../utils/canParseUrl'\nimport { createRequestId } from '../../createRequestId'\nimport { createNetworkError } from './utils/createNetworkError'\nimport { followFetchRedirect } from './utils/followRedirect'\nimport { decompressResponse } from './utils/decompression'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\nimport { FetchResponse } from '../../utils/fetchUtils'\n\nexport class FetchInterceptor extends Interceptor {\n static symbol = Symbol('fetch')\n\n constructor() {\n super(FetchInterceptor.symbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('fetch')\n }\n\n protected async setup() {\n const pureFetch = globalThis.fetch\n\n invariant(\n !(pureFetch as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"fetch\" module: already patched.'\n )\n\n globalThis.fetch = async (input, init) => {\n const requestId = createRequestId()\n\n /**\n * @note Resolve potentially relative request URL\n * against the present `location`. This is mainly\n * for native `fetch` in JSDOM.\n * @see https://github.com/mswjs/msw/issues/1625\n */\n const resolvedInput =\n typeof input === 'string' &&\n typeof location !== 'undefined' &&\n !canParseUrl(input)\n ? new URL(input, location.origin)\n : input\n\n const request = new Request(resolvedInput, init)\n const responsePromise = new DeferredPromise()\n const controller = new RequestController(request)\n\n this.logger.info('[%s] %s', request.method, request.url)\n this.logger.info('awaiting for the mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n this.emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n emitter: this.emitter,\n controller,\n onResponse: async (rawResponse) => {\n this.logger.info('received mocked response!', {\n rawResponse,\n })\n\n // Decompress the mocked response body, if applicable.\n const decompressedStream = decompressResponse(rawResponse)\n const response =\n decompressedStream === null\n ? rawResponse\n : new FetchResponse(decompressedStream, rawResponse)\n\n FetchResponse.setUrl(request.url, response)\n\n /**\n * Undici's handling of following redirect responses.\n * Treat the \"manual\" redirect mode as a regular mocked response.\n * This way, the client can manually follow the redirect it receives.\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173\n */\n if (FetchResponse.isRedirectResponse(response.status)) {\n // Reject the request promise if its `redirect` is set to `error`\n // and it receives a mocked redirect response.\n if (request.redirect === 'error') {\n responsePromise.reject(createNetworkError('unexpected redirect'))\n return\n }\n\n if (request.redirect === 'follow') {\n followFetchRedirect(request, response).then(\n (response) => {\n responsePromise.resolve(response)\n },\n (reason) => {\n responsePromise.reject(reason)\n }\n )\n return\n }\n }\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n // Await the response listeners to finish before resolving\n // the response promise. This ensures all your logic finishes\n // before the interceptor resolves the pending response.\n await emitAsync(this.emitter, 'response', {\n // Clone the mocked response for the \"response\" event listener.\n // This way, the listener can read the response and not lock its body\n // for the actual fetch consumer.\n response: response.clone(),\n isMockedResponse: true,\n request,\n requestId,\n })\n }\n\n responsePromise.resolve(response)\n },\n onRequestError: (response) => {\n this.logger.info('request has errored!', { response })\n responsePromise.reject(createNetworkError(response))\n },\n onError: (error) => {\n this.logger.info('request has been aborted!', { error })\n responsePromise.reject(error)\n },\n })\n\n if (isRequestHandled) {\n this.logger.info('request has been handled, returning mock promise...')\n return responsePromise\n }\n\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n\n return pureFetch(request).then(async (response) => {\n this.logger.info('original fetch performed', response)\n\n if (this.emitter.listenerCount('response') > 0) {\n this.logger.info('emitting the \"response\" event...')\n\n const responseClone = response.clone()\n\n await emitAsync(this.emitter, 'response', {\n response: responseClone,\n isMockedResponse: false,\n request,\n requestId,\n })\n }\n\n return response\n })\n }\n\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.fetch = pureFetch\n\n this.logger.info(\n 'restored native \"globalThis.fetch\"!',\n globalThis.fetch.name\n )\n })\n }\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n try {\n new URL(url)\n return true\n } catch (_error) {\n return false\n }\n}\n","export function createNetworkError(cause?: unknown) {\n return Object.assign(new TypeError('Failed to fetch'), {\n cause,\n })\n}\n","import { createNetworkError } from './createNetworkError'\n\nconst REQUEST_BODY_HEADERS = [\n 'content-encoding',\n 'content-language',\n 'content-location',\n 'content-type',\n 'content-length',\n]\n\nconst kRedirectCount = Symbol('kRedirectCount')\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1210\n */\nexport async function followFetchRedirect(\n request: Request,\n response: Response\n): Promise {\n if (response.status !== 303 && request.body != null) {\n return Promise.reject(createNetworkError())\n }\n\n const requestUrl = new URL(request.url)\n\n let locationUrl: URL\n try {\n // If the location is a relative URL, use the request URL as the base URL.\n locationUrl = new URL(response.headers.get('location')!, request.url) \n } catch (error) {\n return Promise.reject(createNetworkError(error))\n }\n\n if (\n !(locationUrl.protocol === 'http:' || locationUrl.protocol === 'https:')\n ) {\n return Promise.reject(\n createNetworkError('URL scheme must be a HTTP(S) scheme')\n )\n }\n\n if (Reflect.get(request, kRedirectCount) > 20) {\n return Promise.reject(createNetworkError('redirect count exceeded'))\n }\n\n Object.defineProperty(request, kRedirectCount, {\n value: (Reflect.get(request, kRedirectCount) || 0) + 1,\n })\n\n if (\n request.mode === 'cors' &&\n (locationUrl.username || locationUrl.password) &&\n !sameOrigin(requestUrl, locationUrl)\n ) {\n return Promise.reject(\n createNetworkError('cross origin not allowed for request mode \"cors\"')\n )\n }\n\n const requestInit: RequestInit = {}\n\n if (\n ([301, 302].includes(response.status) && request.method === 'POST') ||\n (response.status === 303 && !['HEAD', 'GET'].includes(request.method))\n ) {\n requestInit.method = 'GET'\n requestInit.body = null\n\n REQUEST_BODY_HEADERS.forEach((headerName) => {\n request.headers.delete(headerName)\n })\n }\n\n if (!sameOrigin(requestUrl, locationUrl)) {\n request.headers.delete('authorization')\n request.headers.delete('proxy-authorization')\n request.headers.delete('cookie')\n request.headers.delete('host')\n }\n\n /**\n * @note Undici \"safely\" extracts the request body.\n * I suspect we cannot dispatch this request again\n * since its body has been read and the stream is locked.\n */\n\n requestInit.headers = request.headers\n return fetch(new Request(locationUrl, requestInit))\n}\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/util.js#L761\n */\nfunction sameOrigin(left: URL, right: URL): boolean {\n if (left.origin === right.origin && left.origin === 'null') {\n return true\n }\n\n if (\n left.protocol === right.protocol &&\n left.hostname === right.hostname &&\n left.port === right.port\n ) {\n return true\n }\n\n return false\n}\n","import zlib from 'node:zlib'\n\nexport class BrotliDecompressionStream extends TransformStream {\n constructor() {\n const decompress = zlib.createBrotliDecompress({\n flush: zlib.constants.BROTLI_OPERATION_FLUSH,\n finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH,\n })\n\n super({\n async transform(chunk, controller) {\n const buffer = Buffer.from(chunk)\n\n const decompressed = await new Promise((resolve, reject) => {\n decompress.write(buffer, (error) => {\n if (error) reject(error)\n })\n\n decompress.flush()\n decompress.once('data', (data) => resolve(data))\n decompress.once('error', (error) => reject(error))\n decompress.once('end', () => controller.terminate())\n }).catch((error) => {\n controller.error(error)\n })\n\n controller.enqueue(decompressed)\n },\n })\n }\n}\n","// Import from an internal alias that resolves to different modules\n// depending on the environment. This way, we can keep the fetch interceptor\n// intact while using different strategies for Brotli decompression.\nimport { BrotliDecompressionStream } from 'internal:brotli-decompress'\n\nclass PipelineStream extends TransformStream {\n constructor(\n transformStreams: Array,\n ...strategies: Array\n ) {\n super({}, ...strategies)\n\n const readable = [super.readable as any, ...transformStreams].reduce(\n (readable, transform) => readable.pipeThrough(transform)\n )\n\n Object.defineProperty(this, 'readable', {\n get() {\n return readable\n },\n })\n }\n}\n\nexport function parseContentEncoding(contentEncoding: string): Array {\n return contentEncoding\n .toLowerCase()\n .split(',')\n .map((coding) => coding.trim())\n}\n\nfunction createDecompressionStream(\n contentEncoding: string\n): TransformStream | null {\n if (contentEncoding === '') {\n return null\n }\n\n const codings = parseContentEncoding(contentEncoding)\n\n if (codings.length === 0) {\n return null\n }\n\n const transformers = codings.reduceRight>(\n (transformers, coding) => {\n if (coding === 'gzip' || coding === 'x-gzip') {\n return transformers.concat(new DecompressionStream('gzip'))\n } else if (coding === 'deflate') {\n return transformers.concat(new DecompressionStream('deflate'))\n } else if (coding === 'br') {\n return transformers.concat(new BrotliDecompressionStream())\n } else {\n transformers.length = 0\n }\n\n return transformers\n },\n []\n )\n\n return new PipelineStream(transformers)\n}\n\nexport function decompressResponse(\n response: Response\n): ReadableStream | null {\n if (response.body === null) {\n return null\n }\n\n const decompressionStream = createDecompressionStream(\n response.headers.get('content-encoding') || ''\n )\n\n if (!decompressionStream) {\n return null\n }\n\n // Use `pipeTo` and return the decompression stream's readable\n // instead of `pipeThrough` because that will lock the original\n // response stream, making it unusable as the input to Response.\n response.body.pipeTo(decompressionStream.writable)\n return decompressionStream.readable\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-LK6DILFK.js b/node_modules/@mswjs/interceptors/lib/node/chunk-LK6DILFK.js new file mode 100644 index 0000000000..f41d9eae57 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-LK6DILFK.js @@ -0,0 +1,22 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/utils/bufferUtils.ts +var encoder = new TextEncoder(); +function encodeBuffer(text) { + return encoder.encode(text); +} +function decodeBuffer(buffer, encoding) { + const decoder = new TextDecoder(encoding); + return decoder.decode(buffer); +} +function toArrayBuffer(array) { + return array.buffer.slice( + array.byteOffset, + array.byteOffset + array.byteLength + ); +} + + + + + +exports.encodeBuffer = encodeBuffer; exports.decodeBuffer = decodeBuffer; exports.toArrayBuffer = toArrayBuffer; +//# sourceMappingURL=chunk-LK6DILFK.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-LK6DILFK.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-LK6DILFK.js.map new file mode 100644 index 0000000000..691683680b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-LK6DILFK.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/bufferUtils.ts"],"names":[],"mappings":";AAAA,IAAM,UAAU,IAAI,YAAY;AAEzB,SAAS,aAAa,MAA0B;AACrD,SAAO,QAAQ,OAAO,IAAI;AAC5B;AAEO,SAAS,aAAa,QAAqB,UAA2B;AAC3E,QAAM,UAAU,IAAI,YAAY,QAAQ;AACxC,SAAO,QAAQ,OAAO,MAAM;AAC9B;AAOO,SAAS,cAAc,OAAgC;AAC5D,SAAO,MAAM,OAAO;AAAA,IAClB,MAAM;AAAA,IACN,MAAM,aAAa,MAAM;AAAA,EAC3B;AACF","sourcesContent":["const encoder = new TextEncoder()\n\nexport function encodeBuffer(text: string): Uint8Array {\n return encoder.encode(text)\n}\n\nexport function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string {\n const decoder = new TextDecoder(encoding)\n return decoder.decode(buffer)\n}\n\n/**\n * Create an `ArrayBuffer` from the given `Uint8Array`.\n * Takes the byte offset into account to produce the right buffer\n * in the case when the buffer is bigger than the data view.\n */\nexport function toArrayBuffer(array: Uint8Array): ArrayBuffer {\n return array.buffer.slice(\n array.byteOffset,\n array.byteOffset + array.byteLength\n )\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-OMWE7UVM.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-OMWE7UVM.mjs new file mode 100644 index 0000000000..aea1e2aab8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-OMWE7UVM.mjs @@ -0,0 +1,844 @@ +import { + decodeBuffer, + encodeBuffer, + toArrayBuffer +} from "./chunk-6HYIRFX2.mjs"; +import { + hasConfigurableGlobal +} from "./chunk-TX5GBTFY.mjs"; +import { + IS_PATCHED_MODULE +} from "./chunk-6YM4PLBI.mjs"; +import { + RequestController, + handleRequest +} from "./chunk-5KMS5CTP.mjs"; +import { + FetchResponse, + INTERNAL_REQUEST_ID_HEADER_NAME, + Interceptor, + createRequestId +} from "./chunk-I7HQIBT7.mjs"; + +// src/interceptors/XMLHttpRequest/index.ts +import { invariant as invariant2 } from "outvariant"; + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +import { invariant } from "outvariant"; +import { isNodeProcess } from "is-node-process"; + +// src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts +function concatArrayBuffer(left, right) { + const result = new Uint8Array(left.byteLength + right.byteLength); + result.set(left, 0); + result.set(right, left.byteLength); + return result; +} + +// src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts +var EventPolyfill = class { + constructor(type, options) { + this.NONE = 0; + this.CAPTURING_PHASE = 1; + this.AT_TARGET = 2; + this.BUBBLING_PHASE = 3; + this.type = ""; + this.srcElement = null; + this.currentTarget = null; + this.eventPhase = 0; + this.isTrusted = true; + this.composed = false; + this.cancelable = true; + this.defaultPrevented = false; + this.bubbles = true; + this.lengthComputable = true; + this.loaded = 0; + this.total = 0; + this.cancelBubble = false; + this.returnValue = true; + this.type = type; + this.target = (options == null ? void 0 : options.target) || null; + this.currentTarget = (options == null ? void 0 : options.currentTarget) || null; + this.timeStamp = Date.now(); + } + composedPath() { + return []; + } + initEvent(type, bubbles, cancelable) { + this.type = type; + this.bubbles = !!bubbles; + this.cancelable = !!cancelable; + } + preventDefault() { + this.defaultPrevented = true; + } + stopPropagation() { + } + stopImmediatePropagation() { + } +}; + +// src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts +var ProgressEventPolyfill = class extends EventPolyfill { + constructor(type, init) { + super(type); + this.lengthComputable = (init == null ? void 0 : init.lengthComputable) || false; + this.composed = (init == null ? void 0 : init.composed) || false; + this.loaded = (init == null ? void 0 : init.loaded) || 0; + this.total = (init == null ? void 0 : init.total) || 0; + } +}; + +// src/interceptors/XMLHttpRequest/utils/createEvent.ts +var SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== "undefined"; +function createEvent(target, type, init) { + const progressEvents = [ + "error", + "progress", + "loadstart", + "loadend", + "load", + "timeout", + "abort" + ]; + const ProgressEventClass = SUPPORTS_PROGRESS_EVENT ? ProgressEvent : ProgressEventPolyfill; + const event = progressEvents.includes(type) ? new ProgressEventClass(type, { + lengthComputable: true, + loaded: (init == null ? void 0 : init.loaded) || 0, + total: (init == null ? void 0 : init.total) || 0 + }) : new EventPolyfill(type, { + target, + currentTarget: target + }); + return event; +} + +// src/utils/findPropertySource.ts +function findPropertySource(target, propertyName) { + if (!(propertyName in target)) { + return null; + } + const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName); + if (hasProperty) { + return target; + } + const prototype = Reflect.getPrototypeOf(target); + return prototype ? findPropertySource(prototype, propertyName) : null; +} + +// src/utils/createProxy.ts +function createProxy(target, options) { + const proxy = new Proxy(target, optionsToProxyHandler(options)); + return proxy; +} +function optionsToProxyHandler(options) { + const { constructorCall, methodCall, getProperty, setProperty } = options; + const handler = {}; + if (typeof constructorCall !== "undefined") { + handler.construct = function(target, args, newTarget) { + const next = Reflect.construct.bind(null, target, args, newTarget); + return constructorCall.call(newTarget, args, next); + }; + } + handler.set = function(target, propertyName, nextValue) { + const next = () => { + const propertySource = findPropertySource(target, propertyName) || target; + const ownDescriptors = Reflect.getOwnPropertyDescriptor( + propertySource, + propertyName + ); + if (typeof (ownDescriptors == null ? void 0 : ownDescriptors.set) !== "undefined") { + ownDescriptors.set.apply(target, [nextValue]); + return true; + } + return Reflect.defineProperty(propertySource, propertyName, { + writable: true, + enumerable: true, + configurable: true, + value: nextValue + }); + }; + if (typeof setProperty !== "undefined") { + return setProperty.call(target, [propertyName, nextValue], next); + } + return next(); + }; + handler.get = function(target, propertyName, receiver) { + const next = () => target[propertyName]; + const value = typeof getProperty !== "undefined" ? getProperty.call(target, [propertyName, receiver], next) : next(); + if (typeof value === "function") { + return (...args) => { + const next2 = value.bind(target, ...args); + if (typeof methodCall !== "undefined") { + return methodCall.call(target, [propertyName, args], next2); + } + return next2(); + }; + } + return value; + }; + return handler; +} + +// src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts +function isDomParserSupportedType(type) { + const supportedTypes = [ + "application/xhtml+xml", + "application/xml", + "image/svg+xml", + "text/html", + "text/xml" + ]; + return supportedTypes.some((supportedType) => { + return type.startsWith(supportedType); + }); +} + +// src/utils/parseJson.ts +function parseJson(data) { + try { + const json = JSON.parse(data); + return json; + } catch (_) { + return null; + } +} + +// src/interceptors/XMLHttpRequest/utils/createResponse.ts +function createResponse(request, body) { + const responseBodyOrNull = FetchResponse.isResponseWithBody(request.status) ? body : null; + return new FetchResponse(responseBodyOrNull, { + url: request.responseURL, + status: request.status, + statusText: request.statusText, + headers: createHeadersFromXMLHttpReqestHeaders( + request.getAllResponseHeaders() + ) + }); +} +function createHeadersFromXMLHttpReqestHeaders(headersString) { + const headers = new Headers(); + const lines = headersString.split(/[\r\n]+/); + for (const line of lines) { + if (line.trim() === "") { + continue; + } + const [name, ...parts] = line.split(": "); + const value = parts.join(": "); + headers.append(name, value); + } + return headers; +} + +// src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts +async function getBodyByteLength(input) { + const explicitContentLength = input.headers.get("content-length"); + if (explicitContentLength != null && explicitContentLength !== "") { + return Number(explicitContentLength); + } + const buffer = await input.arrayBuffer(); + return buffer.byteLength; +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts +var kIsRequestHandled = Symbol("kIsRequestHandled"); +var IS_NODE = isNodeProcess(); +var kFetchRequest = Symbol("kFetchRequest"); +var XMLHttpRequestController = class { + constructor(initialRequest, logger) { + this.initialRequest = initialRequest; + this.logger = logger; + this.method = "GET"; + this.url = null; + this[kIsRequestHandled] = false; + this.events = /* @__PURE__ */ new Map(); + this.uploadEvents = /* @__PURE__ */ new Map(); + this.requestId = createRequestId(); + this.requestHeaders = new Headers(); + this.responseBuffer = new Uint8Array(); + this.request = createProxy(initialRequest, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "ontimeout": { + const eventName = propertyName.slice( + 2 + ); + this.request.addEventListener(eventName, nextValue); + return invoke(); + } + default: { + return invoke(); + } + } + }, + methodCall: ([methodName, args], invoke) => { + var _a; + switch (methodName) { + case "open": { + const [method, url] = args; + if (typeof url === "undefined") { + this.method = "GET"; + this.url = toAbsoluteUrl(method); + } else { + this.method = method; + this.url = toAbsoluteUrl(url); + } + this.logger = this.logger.extend(`${this.method} ${this.url.href}`); + this.logger.info("open", this.method, this.url.href); + return invoke(); + } + case "addEventListener": { + const [eventName, listener] = args; + this.registerEvent(eventName, listener); + this.logger.info("addEventListener", eventName, listener); + return invoke(); + } + case "setRequestHeader": { + const [name, value] = args; + this.requestHeaders.set(name, value); + this.logger.info("setRequestHeader", name, value); + return invoke(); + } + case "send": { + const [body] = args; + this.request.addEventListener("load", () => { + if (typeof this.onResponse !== "undefined") { + const fetchResponse = createResponse( + this.request, + /** + * The `response` property is the right way to read + * the ambiguous response body, as the request's "responseType" may differ. + * @see https://xhr.spec.whatwg.org/#the-response-attribute + */ + this.request.response + ); + this.onResponse.call(this, { + response: fetchResponse, + isMockedResponse: this[kIsRequestHandled], + request: fetchRequest, + requestId: this.requestId + }); + } + }); + const requestBody = typeof body === "string" ? encodeBuffer(body) : body; + const fetchRequest = this.toFetchApiRequest(requestBody); + this[kFetchRequest] = fetchRequest.clone(); + const onceRequestSettled = ((_a = this.onRequest) == null ? void 0 : _a.call(this, { + request: fetchRequest, + requestId: this.requestId + })) || Promise.resolve(); + onceRequestSettled.finally(() => { + if (!this[kIsRequestHandled]) { + this.logger.info( + "request callback settled but request has not been handled (readystate %d), performing as-is...", + this.request.readyState + ); + if (IS_NODE) { + this.request.setRequestHeader( + INTERNAL_REQUEST_ID_HEADER_NAME, + this.requestId + ); + } + return invoke(); + } + }); + break; + } + default: { + return invoke(); + } + } + } + }); + define( + this.request, + "upload", + createProxy(this.request.upload, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case "onloadstart": + case "onprogress": + case "onaboart": + case "onerror": + case "onload": + case "ontimeout": + case "onloadend": { + const eventName = propertyName.slice( + 2 + ); + this.registerUploadEvent(eventName, nextValue); + } + } + return invoke(); + }, + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "addEventListener": { + const [eventName, listener] = args; + this.registerUploadEvent(eventName, listener); + this.logger.info("upload.addEventListener", eventName, listener); + return invoke(); + } + } + } + }) + ); + } + registerEvent(eventName, listener) { + const prevEvents = this.events.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.events.set(eventName, nextEvents); + this.logger.info('registered event "%s"', eventName, listener); + } + registerUploadEvent(eventName, listener) { + const prevEvents = this.uploadEvents.get(eventName) || []; + const nextEvents = prevEvents.concat(listener); + this.uploadEvents.set(eventName, nextEvents); + this.logger.info('registered upload event "%s"', eventName, listener); + } + /** + * Responds to the current request with the given + * Fetch API `Response` instance. + */ + async respondWith(response) { + this[kIsRequestHandled] = true; + if (this[kFetchRequest]) { + const totalRequestBodyLength = await getBodyByteLength( + this[kFetchRequest] + ); + this.trigger("loadstart", this.request.upload, { + loaded: 0, + total: totalRequestBodyLength + }); + this.trigger("progress", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("load", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + this.trigger("loadend", this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength + }); + } + this.logger.info( + "responding with a mocked response: %d %s", + response.status, + response.statusText + ); + define(this.request, "status", response.status); + define(this.request, "statusText", response.statusText); + define(this.request, "responseURL", this.url.href); + this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, { + apply: (_, __, args) => { + this.logger.info("getResponseHeader", args[0]); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning null"); + return null; + } + const headerValue = response.headers.get(args[0]); + this.logger.info( + 'resolved response header "%s" to', + args[0], + headerValue + ); + return headerValue; + } + }); + this.request.getAllResponseHeaders = new Proxy( + this.request.getAllResponseHeaders, + { + apply: () => { + this.logger.info("getAllResponseHeaders"); + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info("headers not received yet, returning empty string"); + return ""; + } + const headersList = Array.from(response.headers.entries()); + const allHeaders = headersList.map(([headerName, headerValue]) => { + return `${headerName}: ${headerValue}`; + }).join("\r\n"); + this.logger.info("resolved all response headers to", allHeaders); + return allHeaders; + } + } + ); + Object.defineProperties(this.request, { + response: { + enumerable: true, + configurable: false, + get: () => this.response + }, + responseText: { + enumerable: true, + configurable: false, + get: () => this.responseText + }, + responseXML: { + enumerable: true, + configurable: false, + get: () => this.responseXML + } + }); + const totalResponseBodyLength = await getBodyByteLength(response.clone()); + this.logger.info("calculated response body length", totalResponseBodyLength); + this.trigger("loadstart", this.request, { + loaded: 0, + total: totalResponseBodyLength + }); + this.setReadyState(this.request.HEADERS_RECEIVED); + this.setReadyState(this.request.LOADING); + const finalizeResponse = () => { + this.logger.info("finalizing the mocked response..."); + this.setReadyState(this.request.DONE); + this.trigger("load", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + this.trigger("loadend", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + }; + if (response.body) { + this.logger.info("mocked response has body, streaming..."); + const reader = response.body.getReader(); + const readNextResponseBodyChunk = async () => { + const { value, done } = await reader.read(); + if (done) { + this.logger.info("response body stream done!"); + finalizeResponse(); + return; + } + if (value) { + this.logger.info("read response body chunk:", value); + this.responseBuffer = concatArrayBuffer(this.responseBuffer, value); + this.trigger("progress", this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength + }); + } + readNextResponseBodyChunk(); + }; + readNextResponseBodyChunk(); + } else { + finalizeResponse(); + } + } + responseBufferToText() { + return decodeBuffer(this.responseBuffer); + } + get response() { + this.logger.info( + "getResponse (responseType: %s)", + this.request.responseType + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + switch (this.request.responseType) { + case "json": { + const responseJson = parseJson(this.responseBufferToText()); + this.logger.info("resolved response JSON", responseJson); + return responseJson; + } + case "arraybuffer": { + const arrayBuffer = toArrayBuffer(this.responseBuffer); + this.logger.info("resolved response ArrayBuffer", arrayBuffer); + return arrayBuffer; + } + case "blob": { + const mimeType = this.request.getResponseHeader("Content-Type") || "text/plain"; + const responseBlob = new Blob([this.responseBufferToText()], { + type: mimeType + }); + this.logger.info( + "resolved response Blob (mime type: %s)", + responseBlob, + mimeType + ); + return responseBlob; + } + default: { + const responseText = this.responseBufferToText(); + this.logger.info( + 'resolving "%s" response type as text', + this.request.responseType, + responseText + ); + return responseText; + } + } + } + get responseText() { + invariant( + this.request.responseType === "" || this.request.responseType === "text", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.LOADING && this.request.readyState !== this.request.DONE) { + return ""; + } + const responseText = this.responseBufferToText(); + this.logger.info('getResponseText: "%s"', responseText); + return responseText; + } + get responseXML() { + invariant( + this.request.responseType === "" || this.request.responseType === "document", + "InvalidStateError: The object is in invalid state." + ); + if (this.request.readyState !== this.request.DONE) { + return null; + } + const contentType = this.request.getResponseHeader("Content-Type") || ""; + if (typeof DOMParser === "undefined") { + console.warn( + "Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly." + ); + return null; + } + if (isDomParserSupportedType(contentType)) { + return new DOMParser().parseFromString( + this.responseBufferToText(), + contentType + ); + } + return null; + } + errorWith(error) { + this[kIsRequestHandled] = true; + this.logger.info("responding with an error"); + this.setReadyState(this.request.DONE); + this.trigger("error", this.request); + this.trigger("loadend", this.request); + } + /** + * Transitions this request's `readyState` to the given one. + */ + setReadyState(nextReadyState) { + this.logger.info( + "setReadyState: %d -> %d", + this.request.readyState, + nextReadyState + ); + if (this.request.readyState === nextReadyState) { + this.logger.info("ready state identical, skipping transition..."); + return; + } + define(this.request, "readyState", nextReadyState); + this.logger.info("set readyState to: %d", nextReadyState); + if (nextReadyState !== this.request.UNSENT) { + this.logger.info('triggerring "readystatechange" event...'); + this.trigger("readystatechange", this.request); + } + } + /** + * Triggers given event on the `XMLHttpRequest` instance. + */ + trigger(eventName, target, options) { + const callback = target[`on${eventName}`]; + const event = createEvent(target, eventName, options); + this.logger.info('trigger "%s"', eventName, options || ""); + if (typeof callback === "function") { + this.logger.info('found a direct "%s" callback, calling...', eventName); + callback.call(target, event); + } + const events = target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events; + for (const [registeredEventName, listeners] of events) { + if (registeredEventName === eventName) { + this.logger.info( + 'found %d listener(s) for "%s" event, calling...', + listeners.length, + eventName + ); + listeners.forEach((listener) => listener.call(target, event)); + } + } + } + /** + * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance. + */ + toFetchApiRequest(body) { + this.logger.info("converting request to a Fetch API Request..."); + const resolvedBody = body instanceof Document ? body.documentElement.innerText : body; + const fetchRequest = new Request(this.url.href, { + method: this.method, + headers: this.requestHeaders, + /** + * @see https://xhr.spec.whatwg.org/#cross-origin-credentials + */ + credentials: this.request.withCredentials ? "include" : "same-origin", + body: ["GET", "HEAD"].includes(this.method.toUpperCase()) ? null : resolvedBody + }); + const proxyHeaders = createProxy(fetchRequest.headers, { + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case "append": + case "set": { + const [headerName, headerValue] = args; + this.request.setRequestHeader(headerName, headerValue); + break; + } + case "delete": { + const [headerName] = args; + console.warn( + `XMLHttpRequest: Cannot remove a "${headerName}" header from the Fetch API representation of the "${fetchRequest.method} ${fetchRequest.url}" request. XMLHttpRequest headers cannot be removed.` + ); + break; + } + } + return invoke(); + } + }); + define(fetchRequest, "headers", proxyHeaders); + this.logger.info("converted request to a Fetch API Request!", fetchRequest); + return fetchRequest; + } +}; +kIsRequestHandled, kFetchRequest; +function toAbsoluteUrl(url) { + if (typeof location === "undefined") { + return new URL(url); + } + return new URL(url.toString(), location.href); +} +function define(target, property, value) { + Reflect.defineProperty(target, property, { + // Ensure writable properties to allow redefining readonly properties. + writable: true, + enumerable: true, + value + }); +} + +// src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts +function createXMLHttpRequestProxy({ + emitter, + logger +}) { + const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, { + construct(target, args, newTarget) { + logger.info("constructed new XMLHttpRequest"); + const originalRequest = Reflect.construct( + target, + args, + newTarget + ); + const prototypeDescriptors = Object.getOwnPropertyDescriptors( + target.prototype + ); + for (const propertyName in prototypeDescriptors) { + Reflect.defineProperty( + originalRequest, + propertyName, + prototypeDescriptors[propertyName] + ); + } + const xhrRequestController = new XMLHttpRequestController( + originalRequest, + logger + ); + xhrRequestController.onRequest = async function({ request, requestId }) { + const controller = new RequestController(request); + this.logger.info("awaiting mocked response..."); + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + emitter.listenerCount("request") + ); + const isRequestHandled = await handleRequest({ + request, + requestId, + controller, + emitter, + onResponse: async (response) => { + await this.respondWith(response); + }, + onRequestError: () => { + this.errorWith(new TypeError("Network error")); + }, + onError: (error) => { + this.logger.info("request errored!", { error }); + if (error instanceof Error) { + this.errorWith(error); + } + } + }); + if (!isRequestHandled) { + this.logger.info( + "no mocked response received, performing request as-is..." + ); + } + }; + xhrRequestController.onResponse = async function({ + response, + isMockedResponse, + request, + requestId + }) { + this.logger.info( + 'emitting the "response" event for %s listener(s)...', + emitter.listenerCount("response") + ); + emitter.emit("response", { + response, + isMockedResponse, + request, + requestId + }); + }; + return xhrRequestController.request; + } + }); + return XMLHttpRequestProxy; +} + +// src/interceptors/XMLHttpRequest/index.ts +var _XMLHttpRequestInterceptor = class extends Interceptor { + constructor() { + super(_XMLHttpRequestInterceptor.interceptorSymbol); + } + checkEnvironment() { + return hasConfigurableGlobal("XMLHttpRequest"); + } + setup() { + const logger = this.logger.extend("setup"); + logger.info('patching "XMLHttpRequest" module...'); + const PureXMLHttpRequest = globalThis.XMLHttpRequest; + invariant2( + !PureXMLHttpRequest[IS_PATCHED_MODULE], + 'Failed to patch the "XMLHttpRequest" module: already patched.' + ); + globalThis.XMLHttpRequest = createXMLHttpRequestProxy({ + emitter: this.emitter, + logger: this.logger + }); + logger.info( + 'native "XMLHttpRequest" module patched!', + globalThis.XMLHttpRequest.name + ); + Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true + }); + this.subscriptions.push(() => { + Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, { + value: void 0 + }); + globalThis.XMLHttpRequest = PureXMLHttpRequest; + logger.info( + 'native "XMLHttpRequest" module restored!', + globalThis.XMLHttpRequest.name + ); + }); + } +}; +var XMLHttpRequestInterceptor = _XMLHttpRequestInterceptor; +XMLHttpRequestInterceptor.interceptorSymbol = Symbol("xhr"); + +export { + XMLHttpRequestInterceptor +}; +//# sourceMappingURL=chunk-OMWE7UVM.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-OMWE7UVM.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-OMWE7UVM.mjs.map new file mode 100644 index 0000000000..085f069c19 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-OMWE7UVM.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/XMLHttpRequest/index.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts","../../src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts","../../src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts","../../src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts","../../src/interceptors/XMLHttpRequest/utils/createEvent.ts","../../src/utils/findPropertySource.ts","../../src/utils/createProxy.ts","../../src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts","../../src/utils/parseJson.ts","../../src/interceptors/XMLHttpRequest/utils/createResponse.ts","../../src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts","../../src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { createXMLHttpRequestProxy } from './XMLHttpRequestProxy'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\n\nexport type XMLHttpRequestEmitter = Emitter\n\nexport class XMLHttpRequestInterceptor extends Interceptor {\n static interceptorSymbol = Symbol('xhr')\n\n constructor() {\n super(XMLHttpRequestInterceptor.interceptorSymbol)\n }\n\n protected checkEnvironment() {\n return hasConfigurableGlobal('XMLHttpRequest')\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('patching \"XMLHttpRequest\" module...')\n\n const PureXMLHttpRequest = globalThis.XMLHttpRequest\n\n invariant(\n !(PureXMLHttpRequest as any)[IS_PATCHED_MODULE],\n 'Failed to patch the \"XMLHttpRequest\" module: already patched.'\n )\n\n globalThis.XMLHttpRequest = createXMLHttpRequestProxy({\n emitter: this.emitter,\n logger: this.logger,\n })\n\n logger.info(\n 'native \"XMLHttpRequest\" module patched!',\n globalThis.XMLHttpRequest.name\n )\n\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n\n this.subscriptions.push(() => {\n Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, {\n value: undefined,\n })\n\n globalThis.XMLHttpRequest = PureXMLHttpRequest\n logger.info(\n 'native \"XMLHttpRequest\" module restored!',\n globalThis.XMLHttpRequest.name\n )\n })\n }\n}\n","import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport type { Logger } from '@open-draft/logger'\nimport { concatArrayBuffer } from './utils/concatArrayBuffer'\nimport { createEvent } from './utils/createEvent'\nimport {\n decodeBuffer,\n encodeBuffer,\n toArrayBuffer,\n} from '../../utils/bufferUtils'\nimport { createProxy } from '../../utils/createProxy'\nimport { isDomParserSupportedType } from './utils/isDomParserSupportedType'\nimport { parseJson } from '../../utils/parseJson'\nimport { createResponse } from './utils/createResponse'\nimport { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'\nimport { createRequestId } from '../../createRequestId'\nimport { getBodyByteLength } from './utils/getBodyByteLength'\n\nconst kIsRequestHandled = Symbol('kIsRequestHandled')\nconst IS_NODE = isNodeProcess()\nconst kFetchRequest = Symbol('kFetchRequest')\n\n/**\n * An `XMLHttpRequest` instance controller that allows us\n * to handle any given request instance (e.g. responding to it).\n */\nexport class XMLHttpRequestController {\n public request: XMLHttpRequest\n public requestId: string\n public onRequest?: (\n this: XMLHttpRequestController,\n args: {\n request: Request\n requestId: string\n }\n ) => Promise\n public onResponse?: (\n this: XMLHttpRequestController,\n args: {\n response: Response\n isMockedResponse: boolean\n request: Request\n requestId: string\n }\n ) => void;\n\n [kIsRequestHandled]: boolean;\n [kFetchRequest]?: Request\n private method: string = 'GET'\n private url: URL = null as any\n private requestHeaders: Headers\n private responseBuffer: Uint8Array\n private events: Map>\n private uploadEvents: Map<\n keyof XMLHttpRequestEventTargetEventMap,\n Array\n >\n\n constructor(readonly initialRequest: XMLHttpRequest, public logger: Logger) {\n this[kIsRequestHandled] = false\n\n this.events = new Map()\n this.uploadEvents = new Map()\n this.requestId = createRequestId()\n this.requestHeaders = new Headers()\n this.responseBuffer = new Uint8Array()\n\n this.request = createProxy(initialRequest, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'ontimeout': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n /**\n * @note Proxy callbacks to event listeners because JSDOM has trouble\n * translating these properties to callbacks. It seemed to be operating\n * on events exclusively.\n */\n this.request.addEventListener(eventName, nextValue as any)\n\n return invoke()\n }\n\n default: {\n return invoke()\n }\n }\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'open': {\n const [method, url] = args as [string, string | undefined]\n\n if (typeof url === 'undefined') {\n this.method = 'GET'\n this.url = toAbsoluteUrl(method)\n } else {\n this.method = method\n this.url = toAbsoluteUrl(url)\n }\n\n this.logger = this.logger.extend(`${this.method} ${this.url.href}`)\n this.logger.info('open', this.method, this.url.href)\n\n return invoke()\n }\n\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n\n this.registerEvent(eventName, listener)\n this.logger.info('addEventListener', eventName, listener)\n\n return invoke()\n }\n\n case 'setRequestHeader': {\n const [name, value] = args as [string, string]\n this.requestHeaders.set(name, value)\n\n this.logger.info('setRequestHeader', name, value)\n\n return invoke()\n }\n\n case 'send': {\n const [body] = args as [\n body?: XMLHttpRequestBodyInit | Document | null\n ]\n\n this.request.addEventListener('load', () => {\n if (typeof this.onResponse !== 'undefined') {\n // Create a Fetch API Response representation of whichever\n // response this XMLHttpRequest received. Note those may\n // be either a mocked and the original response.\n const fetchResponse = createResponse(\n this.request,\n /**\n * The `response` property is the right way to read\n * the ambiguous response body, as the request's \"responseType\" may differ.\n * @see https://xhr.spec.whatwg.org/#the-response-attribute\n */\n this.request.response\n )\n\n // Notify the consumer about the response.\n this.onResponse.call(this, {\n response: fetchResponse,\n isMockedResponse: this[kIsRequestHandled],\n request: fetchRequest,\n requestId: this.requestId!,\n })\n }\n })\n\n const requestBody =\n typeof body === 'string' ? encodeBuffer(body) : body\n\n // Delegate request handling to the consumer.\n const fetchRequest = this.toFetchApiRequest(requestBody)\n this[kFetchRequest] = fetchRequest.clone()\n\n const onceRequestSettled =\n this.onRequest?.call(this, {\n request: fetchRequest,\n requestId: this.requestId!,\n }) || Promise.resolve()\n\n onceRequestSettled.finally(() => {\n // If the consumer didn't handle the request (called `.respondWith()`) perform it as-is.\n if (!this[kIsRequestHandled]) {\n this.logger.info(\n 'request callback settled but request has not been handled (readystate %d), performing as-is...',\n this.request.readyState\n )\n\n /**\n * @note Set the intercepted request ID on the original request in Node.js\n * so that if it triggers any other interceptors, they don't attempt\n * to process it once again.\n *\n * For instance, XMLHttpRequest is often implemented via \"http.ClientRequest\"\n * and we don't want for both XHR and ClientRequest interceptors to\n * handle the same request at the same time (e.g. emit the \"response\" event twice).\n */\n if (IS_NODE) {\n this.request.setRequestHeader(\n INTERNAL_REQUEST_ID_HEADER_NAME,\n this.requestId!\n )\n }\n\n return invoke()\n }\n })\n\n break\n }\n\n default: {\n return invoke()\n }\n }\n },\n })\n\n /**\n * Proxy the `.upload` property to gather the event listeners/callbacks.\n */\n define(\n this.request,\n 'upload',\n createProxy(this.request.upload, {\n setProperty: ([propertyName, nextValue], invoke) => {\n switch (propertyName) {\n case 'onloadstart':\n case 'onprogress':\n case 'onaboart':\n case 'onerror':\n case 'onload':\n case 'ontimeout':\n case 'onloadend': {\n const eventName = propertyName.slice(\n 2\n ) as keyof XMLHttpRequestEventTargetEventMap\n\n this.registerUploadEvent(eventName, nextValue as Function)\n }\n }\n\n return invoke()\n },\n methodCall: ([methodName, args], invoke) => {\n switch (methodName) {\n case 'addEventListener': {\n const [eventName, listener] = args as [\n keyof XMLHttpRequestEventTargetEventMap,\n Function\n ]\n this.registerUploadEvent(eventName, listener)\n this.logger.info('upload.addEventListener', eventName, listener)\n\n return invoke()\n }\n }\n },\n })\n )\n }\n\n private registerEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.events.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.events.set(eventName, nextEvents)\n\n this.logger.info('registered event \"%s\"', eventName, listener)\n }\n\n private registerUploadEvent(\n eventName: keyof XMLHttpRequestEventTargetEventMap,\n listener: Function\n ): void {\n const prevEvents = this.uploadEvents.get(eventName) || []\n const nextEvents = prevEvents.concat(listener)\n this.uploadEvents.set(eventName, nextEvents)\n\n this.logger.info('registered upload event \"%s\"', eventName, listener)\n }\n\n /**\n * Responds to the current request with the given\n * Fetch API `Response` instance.\n */\n public async respondWith(response: Response): Promise {\n /**\n * @note Since `XMLHttpRequestController` delegates the handling of the responses\n * to the \"load\" event listener that doesn't distinguish between the mocked and original\n * responses, mark the request that had a mocked response with a corresponding symbol.\n *\n * Mark this request as having a mocked response immediately since\n * calculating request/response total body length is asynchronous.\n */\n this[kIsRequestHandled] = true\n\n /**\n * Dispatch request upload events for requests with a body.\n * @see https://github.com/mswjs/interceptors/issues/573\n */\n if (this[kFetchRequest]) {\n const totalRequestBodyLength = await getBodyByteLength(\n this[kFetchRequest]\n )\n\n this.trigger('loadstart', this.request.upload, {\n loaded: 0,\n total: totalRequestBodyLength,\n })\n this.trigger('progress', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('load', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n this.trigger('loadend', this.request.upload, {\n loaded: totalRequestBodyLength,\n total: totalRequestBodyLength,\n })\n }\n\n this.logger.info(\n 'responding with a mocked response: %d %s',\n response.status,\n response.statusText\n )\n\n define(this.request, 'status', response.status)\n define(this.request, 'statusText', response.statusText)\n define(this.request, 'responseURL', this.url.href)\n\n this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, {\n apply: (_, __, args: [name: string]) => {\n this.logger.info('getResponseHeader', args[0])\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning null')\n\n // Headers not received yet, nothing to return.\n return null\n }\n\n const headerValue = response.headers.get(args[0])\n this.logger.info(\n 'resolved response header \"%s\" to',\n args[0],\n headerValue\n )\n\n return headerValue\n },\n })\n\n this.request.getAllResponseHeaders = new Proxy(\n this.request.getAllResponseHeaders,\n {\n apply: () => {\n this.logger.info('getAllResponseHeaders')\n\n if (this.request.readyState < this.request.HEADERS_RECEIVED) {\n this.logger.info('headers not received yet, returning empty string')\n\n // Headers not received yet, nothing to return.\n return ''\n }\n\n const headersList = Array.from(response.headers.entries())\n const allHeaders = headersList\n .map(([headerName, headerValue]) => {\n return `${headerName}: ${headerValue}`\n })\n .join('\\r\\n')\n\n this.logger.info('resolved all response headers to', allHeaders)\n\n return allHeaders\n },\n }\n )\n\n // Update the response getters to resolve against the mocked response.\n Object.defineProperties(this.request, {\n response: {\n enumerable: true,\n configurable: false,\n get: () => this.response,\n },\n responseText: {\n enumerable: true,\n configurable: false,\n get: () => this.responseText,\n },\n responseXML: {\n enumerable: true,\n configurable: false,\n get: () => this.responseXML,\n },\n })\n\n const totalResponseBodyLength = await getBodyByteLength(response.clone())\n\n this.logger.info('calculated response body length', totalResponseBodyLength)\n\n this.trigger('loadstart', this.request, {\n loaded: 0,\n total: totalResponseBodyLength,\n })\n\n this.setReadyState(this.request.HEADERS_RECEIVED)\n this.setReadyState(this.request.LOADING)\n\n const finalizeResponse = () => {\n this.logger.info('finalizing the mocked response...')\n\n this.setReadyState(this.request.DONE)\n\n this.trigger('load', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n\n this.trigger('loadend', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n if (response.body) {\n this.logger.info('mocked response has body, streaming...')\n\n const reader = response.body.getReader()\n\n const readNextResponseBodyChunk = async () => {\n const { value, done } = await reader.read()\n\n if (done) {\n this.logger.info('response body stream done!')\n finalizeResponse()\n return\n }\n\n if (value) {\n this.logger.info('read response body chunk:', value)\n this.responseBuffer = concatArrayBuffer(this.responseBuffer, value)\n\n this.trigger('progress', this.request, {\n loaded: this.responseBuffer.byteLength,\n total: totalResponseBodyLength,\n })\n }\n\n readNextResponseBodyChunk()\n }\n\n readNextResponseBodyChunk()\n } else {\n finalizeResponse()\n }\n }\n\n private responseBufferToText(): string {\n return decodeBuffer(this.responseBuffer)\n }\n\n get response(): unknown {\n this.logger.info(\n 'getResponse (responseType: %s)',\n this.request.responseType\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n switch (this.request.responseType) {\n case 'json': {\n const responseJson = parseJson(this.responseBufferToText())\n this.logger.info('resolved response JSON', responseJson)\n\n return responseJson\n }\n\n case 'arraybuffer': {\n const arrayBuffer = toArrayBuffer(this.responseBuffer)\n this.logger.info('resolved response ArrayBuffer', arrayBuffer)\n\n return arrayBuffer\n }\n\n case 'blob': {\n const mimeType =\n this.request.getResponseHeader('Content-Type') || 'text/plain'\n const responseBlob = new Blob([this.responseBufferToText()], {\n type: mimeType,\n })\n\n this.logger.info(\n 'resolved response Blob (mime type: %s)',\n responseBlob,\n mimeType\n )\n\n return responseBlob\n }\n\n default: {\n const responseText = this.responseBufferToText()\n this.logger.info(\n 'resolving \"%s\" response type as text',\n this.request.responseType,\n responseText\n )\n\n return responseText\n }\n }\n }\n\n get responseText(): string {\n /**\n * Throw when trying to read the response body as text when the\n * \"responseType\" doesn't expect text. This just respects the spec better.\n * @see https://xhr.spec.whatwg.org/#the-responsetext-attribute\n */\n invariant(\n this.request.responseType === '' || this.request.responseType === 'text',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (\n this.request.readyState !== this.request.LOADING &&\n this.request.readyState !== this.request.DONE\n ) {\n return ''\n }\n\n const responseText = this.responseBufferToText()\n this.logger.info('getResponseText: \"%s\"', responseText)\n\n return responseText\n }\n\n get responseXML(): Document | null {\n invariant(\n this.request.responseType === '' ||\n this.request.responseType === 'document',\n 'InvalidStateError: The object is in invalid state.'\n )\n\n if (this.request.readyState !== this.request.DONE) {\n return null\n }\n\n const contentType = this.request.getResponseHeader('Content-Type') || ''\n\n if (typeof DOMParser === 'undefined') {\n console.warn(\n 'Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly.'\n )\n return null\n }\n\n if (isDomParserSupportedType(contentType)) {\n return new DOMParser().parseFromString(\n this.responseBufferToText(),\n contentType\n )\n }\n\n return null\n }\n\n public errorWith(error?: Error): void {\n /**\n * @note Mark this request as handled even if it received a mock error.\n * This prevents the controller from trying to perform this request as-is.\n */\n this[kIsRequestHandled] = true\n this.logger.info('responding with an error')\n\n this.setReadyState(this.request.DONE)\n this.trigger('error', this.request)\n this.trigger('loadend', this.request)\n }\n\n /**\n * Transitions this request's `readyState` to the given one.\n */\n private setReadyState(nextReadyState: number): void {\n this.logger.info(\n 'setReadyState: %d -> %d',\n this.request.readyState,\n nextReadyState\n )\n\n if (this.request.readyState === nextReadyState) {\n this.logger.info('ready state identical, skipping transition...')\n return\n }\n\n define(this.request, 'readyState', nextReadyState)\n\n this.logger.info('set readyState to: %d', nextReadyState)\n\n if (nextReadyState !== this.request.UNSENT) {\n this.logger.info('triggerring \"readystatechange\" event...')\n\n this.trigger('readystatechange', this.request)\n }\n }\n\n /**\n * Triggers given event on the `XMLHttpRequest` instance.\n */\n private trigger<\n EventName extends keyof (XMLHttpRequestEventTargetEventMap & {\n readystatechange: ProgressEvent\n })\n >(\n eventName: EventName,\n target: XMLHttpRequest | XMLHttpRequestUpload,\n options?: ProgressEventInit\n ): void {\n const callback = (target as XMLHttpRequest)[`on${eventName}`]\n const event = createEvent(target, eventName, options)\n\n this.logger.info('trigger \"%s\"', eventName, options || '')\n\n // Invoke direct callbacks.\n if (typeof callback === 'function') {\n this.logger.info('found a direct \"%s\" callback, calling...', eventName)\n callback.call(target as XMLHttpRequest, event)\n }\n\n // Invoke event listeners.\n const events =\n target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events\n\n for (const [registeredEventName, listeners] of events) {\n if (registeredEventName === eventName) {\n this.logger.info(\n 'found %d listener(s) for \"%s\" event, calling...',\n listeners.length,\n eventName\n )\n\n listeners.forEach((listener) => listener.call(target, event))\n }\n }\n }\n\n /**\n * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance.\n */\n private toFetchApiRequest(\n body: XMLHttpRequestBodyInit | Document | null | undefined\n ): Request {\n this.logger.info('converting request to a Fetch API Request...')\n\n // If the `Document` is used as the body of this XMLHttpRequest,\n // set its inner text as the Fetch API Request body.\n const resolvedBody =\n body instanceof Document ? body.documentElement.innerText : body\n\n const fetchRequest = new Request(this.url.href, {\n method: this.method,\n headers: this.requestHeaders,\n /**\n * @see https://xhr.spec.whatwg.org/#cross-origin-credentials\n */\n credentials: this.request.withCredentials ? 'include' : 'same-origin',\n body: ['GET', 'HEAD'].includes(this.method.toUpperCase())\n ? null\n : resolvedBody,\n })\n\n const proxyHeaders = createProxy(fetchRequest.headers, {\n methodCall: ([methodName, args], invoke) => {\n // Forward the latest state of the internal request headers\n // because the interceptor might have modified them\n // without responding to the request.\n switch (methodName) {\n case 'append':\n case 'set': {\n const [headerName, headerValue] = args as [string, string]\n this.request.setRequestHeader(headerName, headerValue)\n break\n }\n\n case 'delete': {\n const [headerName] = args as [string]\n console.warn(\n `XMLHttpRequest: Cannot remove a \"${headerName}\" header from the Fetch API representation of the \"${fetchRequest.method} ${fetchRequest.url}\" request. XMLHttpRequest headers cannot be removed.`\n )\n break\n }\n }\n\n return invoke()\n },\n })\n define(fetchRequest, 'headers', proxyHeaders)\n\n this.logger.info('converted request to a Fetch API Request!', fetchRequest)\n\n return fetchRequest\n }\n}\n\nfunction toAbsoluteUrl(url: string | URL): URL {\n /**\n * @note XMLHttpRequest interceptor may run in environments\n * that implement XMLHttpRequest but don't implement \"location\"\n * (for example, React Native). If that's the case, return the\n * input URL as-is (nothing to be relative to).\n * @see https://github.com/mswjs/msw/issues/1777\n */\n if (typeof location === 'undefined') {\n return new URL(url)\n }\n\n return new URL(url.toString(), location.href)\n}\n\nfunction define(\n target: object,\n property: string | symbol,\n value: unknown\n): void {\n Reflect.defineProperty(target, property, {\n // Ensure writable properties to allow redefining readonly properties.\n writable: true,\n enumerable: true,\n value,\n })\n}\n","/**\n * Concatenate two `Uint8Array` buffers.\n */\nexport function concatArrayBuffer(\n left: Uint8Array,\n right: Uint8Array\n): Uint8Array {\n const result = new Uint8Array(left.byteLength + right.byteLength)\n result.set(left, 0)\n result.set(right, left.byteLength)\n return result\n}\n","export class EventPolyfill implements Event {\n readonly NONE = 0\n readonly CAPTURING_PHASE = 1\n readonly AT_TARGET = 2\n readonly BUBBLING_PHASE = 3\n\n public type: string = ''\n public srcElement: EventTarget | null = null\n public target: EventTarget | null\n public currentTarget: EventTarget | null = null\n public eventPhase: number = 0\n public timeStamp: number\n public isTrusted: boolean = true\n public composed: boolean = false\n public cancelable: boolean = true\n public defaultPrevented: boolean = false\n public bubbles: boolean = true\n public lengthComputable: boolean = true\n public loaded: number = 0\n public total: number = 0\n\n cancelBubble: boolean = false\n returnValue: boolean = true\n\n constructor(\n type: string,\n options?: { target: EventTarget; currentTarget: EventTarget }\n ) {\n this.type = type\n this.target = options?.target || null\n this.currentTarget = options?.currentTarget || null\n this.timeStamp = Date.now()\n }\n\n public composedPath(): EventTarget[] {\n return []\n }\n\n public initEvent(type: string, bubbles?: boolean, cancelable?: boolean) {\n this.type = type\n this.bubbles = !!bubbles\n this.cancelable = !!cancelable\n }\n\n public preventDefault() {\n this.defaultPrevented = true\n }\n\n public stopPropagation() {}\n public stopImmediatePropagation() {}\n}\n","import { EventPolyfill } from './EventPolyfill'\n\nexport class ProgressEventPolyfill extends EventPolyfill {\n readonly lengthComputable: boolean\n readonly composed: boolean\n readonly loaded: number\n readonly total: number\n\n constructor(type: string, init?: ProgressEventInit) {\n super(type)\n\n this.lengthComputable = init?.lengthComputable || false\n this.composed = init?.composed || false\n this.loaded = init?.loaded || 0\n this.total = init?.total || 0\n }\n}\n","import { EventPolyfill } from '../polyfills/EventPolyfill'\nimport { ProgressEventPolyfill } from '../polyfills/ProgressEventPolyfill'\n\nconst SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== 'undefined'\n\nexport function createEvent(\n target: XMLHttpRequest | XMLHttpRequestUpload,\n type: string,\n init?: ProgressEventInit\n): EventPolyfill | ProgressEvent {\n const progressEvents = [\n 'error',\n 'progress',\n 'loadstart',\n 'loadend',\n 'load',\n 'timeout',\n 'abort',\n ]\n\n /**\n * `ProgressEvent` is not supported in React Native.\n * @see https://github.com/mswjs/interceptors/issues/40\n */\n const ProgressEventClass = SUPPORTS_PROGRESS_EVENT\n ? ProgressEvent\n : ProgressEventPolyfill\n\n const event = progressEvents.includes(type)\n ? new ProgressEventClass(type, {\n lengthComputable: true,\n loaded: init?.loaded || 0,\n total: init?.total || 0,\n })\n : new EventPolyfill(type, {\n target,\n currentTarget: target,\n })\n\n return event\n}\n","/**\n * Returns the source object of the given property on the target object\n * (the target itself, any parent in its prototype, or null).\n */\nexport function findPropertySource(\n target: object,\n propertyName: string | symbol\n): object | null {\n if (!(propertyName in target)) {\n return null\n }\n\n const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName)\n if (hasProperty) {\n return target\n }\n\n const prototype = Reflect.getPrototypeOf(target)\n return prototype ? findPropertySource(prototype, propertyName) : null\n}\n","import { findPropertySource } from './findPropertySource'\n\nexport interface ProxyOptions> {\n constructorCall?(args: Array, next: NextFunction): Target\n\n methodCall?(\n this: Target,\n data: [methodName: F, args: Array],\n next: NextFunction\n ): void\n\n setProperty?(\n data: [propertyName: string | symbol, nextValue: unknown],\n next: NextFunction\n ): boolean\n\n getProperty?(\n data: [propertyName: string | symbol, receiver: Target],\n next: NextFunction\n ): void\n}\n\nexport type NextFunction = () => ReturnType\n\nexport function createProxy(\n target: Target,\n options: ProxyOptions\n): Target {\n const proxy = new Proxy(target, optionsToProxyHandler(options))\n\n return proxy\n}\n\nfunction optionsToProxyHandler>(\n options: ProxyOptions\n): ProxyHandler {\n const { constructorCall, methodCall, getProperty, setProperty } = options\n const handler: ProxyHandler = {}\n\n if (typeof constructorCall !== 'undefined') {\n handler.construct = function (target, args, newTarget) {\n const next = Reflect.construct.bind(null, target as any, args, newTarget)\n return constructorCall.call(newTarget, args, next)\n }\n }\n\n handler.set = function (target, propertyName, nextValue) {\n const next = () => {\n const propertySource = findPropertySource(target, propertyName) || target\n const ownDescriptors = Reflect.getOwnPropertyDescriptor(\n propertySource,\n propertyName\n )\n\n // Respect any custom setters present for this property.\n if (typeof ownDescriptors?.set !== 'undefined') {\n ownDescriptors.set.apply(target, [nextValue])\n return true\n }\n\n // Otherwise, set the property on the source.\n return Reflect.defineProperty(propertySource, propertyName, {\n writable: true,\n enumerable: true,\n configurable: true,\n value: nextValue,\n })\n }\n\n if (typeof setProperty !== 'undefined') {\n return setProperty.call(target, [propertyName, nextValue], next)\n }\n\n return next()\n }\n\n handler.get = function (target, propertyName, receiver) {\n /**\n * @note Using `Reflect.get()` here causes \"TypeError: Illegal invocation\".\n */\n const next = () => target[propertyName as any]\n\n const value =\n typeof getProperty !== 'undefined'\n ? getProperty.call(target, [propertyName, receiver], next)\n : next()\n\n if (typeof value === 'function') {\n return (...args: Array) => {\n const next = value.bind(target, ...args)\n\n if (typeof methodCall !== 'undefined') {\n return methodCall.call(target, [propertyName as any, args], next)\n }\n\n return next()\n }\n }\n\n return value\n }\n\n return handler\n}\n","export function isDomParserSupportedType(\n type: string\n): type is DOMParserSupportedType {\n const supportedTypes: Array = [\n 'application/xhtml+xml',\n 'application/xml',\n 'image/svg+xml',\n 'text/html',\n 'text/xml',\n ]\n return supportedTypes.some((supportedType) => {\n return type.startsWith(supportedType)\n })\n}\n","/**\n * Parses a given string into JSON.\n * Gracefully handles invalid JSON by returning `null`.\n */\nexport function parseJson(data: string): Record | null {\n try {\n const json = JSON.parse(data)\n return json\n } catch (_) {\n return null\n }\n}\n","import { FetchResponse } from '../../../utils/fetchUtils'\n\n/**\n * Creates a Fetch API `Response` instance from the given\n * `XMLHttpRequest` instance and a response body.\n */\nexport function createResponse(\n request: XMLHttpRequest,\n body: BodyInit | null\n): Response {\n /**\n * Handle XMLHttpRequest responses that must have null as the\n * response body when represented using Fetch API Response.\n * XMLHttpRequest response will always have an empty string\n * as the \"request.response\" in those cases, resulting in an error\n * when constructing a Response instance.\n * @see https://github.com/mswjs/interceptors/issues/379\n */\n const responseBodyOrNull = FetchResponse.isResponseWithBody(request.status)\n ? body\n : null\n\n return new FetchResponse(responseBodyOrNull, {\n url: request.responseURL,\n status: request.status,\n statusText: request.statusText,\n headers: createHeadersFromXMLHttpReqestHeaders(\n request.getAllResponseHeaders()\n ),\n })\n}\n\nfunction createHeadersFromXMLHttpReqestHeaders(headersString: string): Headers {\n const headers = new Headers()\n\n const lines = headersString.split(/[\\r\\n]+/)\n for (const line of lines) {\n if (line.trim() === '') {\n continue\n }\n\n const [name, ...parts] = line.split(': ')\n const value = parts.join(': ')\n\n headers.append(name, value)\n }\n\n return headers\n}\n","/**\n * Return a total byte length of the given request/response body.\n * If the `Content-Length` header is present, it will be used as the byte length.\n */\nexport async function getBodyByteLength(\n input: Request | Response\n): Promise {\n const explicitContentLength = input.headers.get('content-length')\n\n if (explicitContentLength != null && explicitContentLength !== '') {\n return Number(explicitContentLength)\n }\n\n const buffer = await input.arrayBuffer()\n return buffer.byteLength\n}\n","import type { Logger } from '@open-draft/logger'\nimport { XMLHttpRequestEmitter } from '.'\nimport { RequestController } from '../../RequestController'\nimport { XMLHttpRequestController } from './XMLHttpRequestController'\nimport { handleRequest } from '../../utils/handleRequest'\n\nexport interface XMLHttpRequestProxyOptions {\n emitter: XMLHttpRequestEmitter\n logger: Logger\n}\n\n/**\n * Create a proxied `XMLHttpRequest` class.\n * The proxied class establishes spies on certain methods,\n * allowing us to intercept requests and respond to them.\n */\nexport function createXMLHttpRequestProxy({\n emitter,\n logger,\n}: XMLHttpRequestProxyOptions) {\n const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, {\n construct(target, args, newTarget) {\n logger.info('constructed new XMLHttpRequest')\n\n const originalRequest = Reflect.construct(\n target,\n args,\n newTarget\n ) as XMLHttpRequest\n\n /**\n * @note Forward prototype descriptors onto the proxied object.\n * XMLHttpRequest is implemented in JSDOM in a way that assigns\n * a bunch of descriptors, like \"set responseType()\" on the prototype.\n * With this propagation, we make sure that those descriptors trigger\n * when the user operates with the proxied request instance.\n */\n const prototypeDescriptors = Object.getOwnPropertyDescriptors(\n target.prototype\n )\n for (const propertyName in prototypeDescriptors) {\n Reflect.defineProperty(\n originalRequest,\n propertyName,\n prototypeDescriptors[propertyName]\n )\n }\n\n const xhrRequestController = new XMLHttpRequestController(\n originalRequest,\n logger\n )\n\n xhrRequestController.onRequest = async function ({ request, requestId }) {\n const controller = new RequestController(request)\n\n this.logger.info('awaiting mocked response...')\n\n this.logger.info(\n 'emitting the \"request\" event for %s listener(s)...',\n emitter.listenerCount('request')\n )\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n controller,\n emitter,\n onResponse: async (response) => {\n await this.respondWith(response)\n },\n onRequestError: () => {\n this.errorWith(new TypeError('Network error'))\n },\n onError: (error) => {\n this.logger.info('request errored!', { error })\n\n if (error instanceof Error) {\n this.errorWith(error)\n }\n },\n })\n\n if (!isRequestHandled) {\n this.logger.info(\n 'no mocked response received, performing request as-is...'\n )\n }\n }\n\n xhrRequestController.onResponse = async function ({\n response,\n isMockedResponse,\n request,\n requestId,\n }) {\n this.logger.info(\n 'emitting the \"response\" event for %s listener(s)...',\n emitter.listenerCount('response')\n )\n\n emitter.emit('response', {\n response,\n isMockedResponse,\n request,\n requestId,\n })\n }\n\n // Return the proxied request from the controller\n // so that the controller can react to the consumer's interactions\n // with this request (opening/sending/etc).\n return xhrRequestController.request\n },\n })\n\n return XMLHttpRequestProxy\n}\n"],"mappings":"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","names":["invariant","next","invariant"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-PFGO5BSM.js b/node_modules/@mswjs/interceptors/lib/node/chunk-PFGO5BSM.js new file mode 100644 index 0000000000..3206fc0cb7 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-PFGO5BSM.js @@ -0,0 +1,25 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/utils/hasConfigurableGlobal.ts +function hasConfigurableGlobal(propertyName) { + const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName); + if (typeof descriptor === "undefined") { + return false; + } + if (typeof descriptor.get === "function" && typeof descriptor.get() === "undefined") { + return false; + } + if (typeof descriptor.get === "undefined" && descriptor.value == null) { + return false; + } + if (typeof descriptor.set === "undefined" && !descriptor.configurable) { + console.error( + `[MSW] Failed to apply interceptor: the global \`${propertyName}\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.` + ); + return false; + } + return true; +} + + + +exports.hasConfigurableGlobal = hasConfigurableGlobal; +//# sourceMappingURL=chunk-PFGO5BSM.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-PFGO5BSM.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-PFGO5BSM.js.map new file mode 100644 index 0000000000..4069b5ab7b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-PFGO5BSM.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/hasConfigurableGlobal.ts"],"names":[],"mappings":";AAIO,SAAS,sBAAsB,cAA+B;AACnE,QAAM,aAAa,OAAO,yBAAyB,YAAY,YAAY;AAG3E,MAAI,OAAO,eAAe,aAAa;AACrC,WAAO;AAAA,EACT;AAGA,MACE,OAAO,WAAW,QAAQ,cAC1B,OAAO,WAAW,IAAI,MAAM,aAC5B;AACA,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,WAAW,QAAQ,eAAe,WAAW,SAAS,MAAM;AACrE,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,QAAQ,eAAe,CAAC,WAAW,cAAc;AACrE,YAAQ;AAAA,MACN,mDAAmD;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT","sourcesContent":["/**\n * Returns a boolean indicating whether the given global property\n * is defined and is configurable.\n */\nexport function hasConfigurableGlobal(propertyName: string): boolean {\n const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName)\n\n // The property is not set at all.\n if (typeof descriptor === 'undefined') {\n return false\n }\n\n // The property is set to a getter that returns undefined.\n if (\n typeof descriptor.get === 'function' &&\n typeof descriptor.get() === 'undefined'\n ) {\n return false\n }\n\n // The property is set to a value equal to undefined.\n if (typeof descriptor.get === 'undefined' && descriptor.value == null) {\n return false\n }\n\n if (typeof descriptor.set === 'undefined' && !descriptor.configurable) {\n console.error(\n `[MSW] Failed to apply interceptor: the global \\`${propertyName}\\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.`\n )\n return false\n }\n\n return true\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-PJA4E426.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-PJA4E426.mjs new file mode 100644 index 0000000000..e3d8725da8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-PJA4E426.mjs @@ -0,0 +1,51 @@ +import { + Interceptor +} from "./chunk-I7HQIBT7.mjs"; + +// src/BatchInterceptor.ts +var BatchInterceptor = class extends Interceptor { + constructor(options) { + BatchInterceptor.symbol = Symbol(options.name); + super(BatchInterceptor.symbol); + this.interceptors = options.interceptors; + } + setup() { + const logger = this.logger.extend("setup"); + logger.info("applying all %d interceptors...", this.interceptors.length); + for (const interceptor of this.interceptors) { + logger.info('applying "%s" interceptor...', interceptor.constructor.name); + interceptor.apply(); + logger.info("adding interceptor dispose subscription"); + this.subscriptions.push(() => interceptor.dispose()); + } + } + on(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.on(event, listener); + } + return this; + } + once(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.once(event, listener); + } + return this; + } + off(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.off(event, listener); + } + return this; + } + removeAllListeners(event) { + for (const interceptors of this.interceptors) { + interceptors.removeAllListeners(event); + } + return this; + } +}; + +export { + BatchInterceptor +}; +//# sourceMappingURL=chunk-PJA4E426.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-PJA4E426.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-PJA4E426.mjs.map new file mode 100644 index 0000000000..9569e4edae --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-PJA4E426.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/BatchInterceptor.ts"],"sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray>\n> = InterceptorList extends ReadonlyArray\n ? InterceptorType extends Interceptor\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray>,\n Events extends EventMap = ExtractEventMapType\n> extends Interceptor {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n"],"mappings":";;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-QFFDMWKW.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-QFFDMWKW.mjs new file mode 100644 index 0000000000..12a60853e3 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-QFFDMWKW.mjs @@ -0,0 +1,1053 @@ +import { + RequestController, + createServerErrorResponse, + emitAsync, + handleRequest, + isPropertyAccessible +} from "./chunk-5KMS5CTP.mjs"; +import { + FetchResponse, + INTERNAL_REQUEST_ID_HEADER_NAME, + Interceptor, + createRequestId +} from "./chunk-I7HQIBT7.mjs"; + +// src/interceptors/ClientRequest/index.ts +import http2 from "http"; +import https2 from "https"; + +// src/interceptors/ClientRequest/MockHttpSocket.ts +import net2 from "net"; +import { + HTTPParser +} from "_http_common"; +import { STATUS_CODES, IncomingMessage, ServerResponse } from "http"; +import { Readable } from "stream"; +import { invariant } from "outvariant"; + +// src/interceptors/Socket/MockSocket.ts +import net from "net"; + +// src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +function normalizeSocketWriteArgs(args) { + const normalized = [args[0], void 0, void 0]; + if (typeof args[1] === "string") { + normalized[1] = args[1]; + } else if (typeof args[1] === "function") { + normalized[2] = args[1]; + } + if (typeof args[2] === "function") { + normalized[2] = args[2]; + } + return normalized; +} + +// src/interceptors/Socket/MockSocket.ts +var MockSocket = class extends net.Socket { + constructor(options) { + super(); + this.options = options; + this.connecting = false; + this.connect(); + this._final = (callback) => { + callback(null); + }; + } + connect() { + this.connecting = true; + return this; + } + write(...args) { + const [chunk, encoding, callback] = normalizeSocketWriteArgs( + args + ); + this.options.write(chunk, encoding, callback); + return true; + } + end(...args) { + const [chunk, encoding, callback] = normalizeSocketWriteArgs( + args + ); + this.options.write(chunk, encoding, callback); + return super.end.apply(this, args); + } + push(chunk, encoding) { + this.options.read(chunk, encoding); + return super.push(chunk, encoding); + } +}; + +// src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +function baseUrlFromConnectionOptions(options) { + if ("href" in options) { + return new URL(options.href); + } + const protocol = options.port === 443 ? "https:" : "http:"; + const host = options.host; + const url = new URL(`${protocol}//${host}`); + if (options.port) { + url.port = options.port.toString(); + } + if (options.path) { + url.pathname = options.path; + } + if (options.auth) { + const [username, password] = options.auth.split(":"); + url.username = username; + url.password = password; + } + return url; +} + +// src/interceptors/ClientRequest/utils/recordRawHeaders.ts +var kRawHeaders = Symbol("kRawHeaders"); +var kRestorePatches = Symbol("kRestorePatches"); +function recordRawHeader(headers, args, behavior) { + ensureRawHeadersSymbol(headers, []); + const rawHeaders = Reflect.get(headers, kRawHeaders); + if (behavior === "set") { + for (let index = rawHeaders.length - 1; index >= 0; index--) { + if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) { + rawHeaders.splice(index, 1); + } + } + } + rawHeaders.push(args); +} +function ensureRawHeadersSymbol(headers, rawHeaders) { + if (Reflect.has(headers, kRawHeaders)) { + return; + } + defineRawHeadersSymbol(headers, rawHeaders); +} +function defineRawHeadersSymbol(headers, rawHeaders) { + Object.defineProperty(headers, kRawHeaders, { + value: rawHeaders, + enumerable: false, + // Mark the symbol as configurable so its value can be overridden. + // Overrides happen when merging raw headers from multiple sources. + // E.g. new Request(new Request(url, { headers }), { headers }) + configurable: true + }); +} +function recordRawFetchHeaders() { + if (Reflect.get(Headers, kRestorePatches)) { + return Reflect.get(Headers, kRestorePatches); + } + const { + Headers: OriginalHeaders, + Request: OriginalRequest, + Response: OriginalResponse + } = globalThis; + const { set, append, delete: headersDeleteMethod } = Headers.prototype; + Object.defineProperty(Headers, kRestorePatches, { + value: () => { + Headers.prototype.set = set; + Headers.prototype.append = append; + Headers.prototype.delete = headersDeleteMethod; + globalThis.Headers = OriginalHeaders; + globalThis.Request = OriginalRequest; + globalThis.Response = OriginalResponse; + Reflect.deleteProperty(Headers, kRestorePatches); + }, + enumerable: false, + /** + * @note Mark this property as configurable + * so we can delete it using `Reflect.delete` during cleanup. + */ + configurable: true + }); + Object.defineProperty(globalThis, "Headers", { + enumerable: true, + writable: true, + value: new Proxy(Headers, { + construct(target, args, newTarget) { + const headersInit = args[0] || []; + if (headersInit instanceof Headers && Reflect.has(headersInit, kRawHeaders)) { + const headers2 = Reflect.construct( + target, + [Reflect.get(headersInit, kRawHeaders)], + newTarget + ); + ensureRawHeadersSymbol(headers2, [ + /** + * @note Spread the retrieved headers to clone them. + * This prevents multiple Headers instances from pointing + * at the same internal "rawHeaders" array. + */ + ...Reflect.get(headersInit, kRawHeaders) + ]); + return headers2; + } + const headers = Reflect.construct(target, args, newTarget); + if (!Reflect.has(headers, kRawHeaders)) { + const rawHeadersInit = Array.isArray(headersInit) ? headersInit : Object.entries(headersInit); + ensureRawHeadersSymbol(headers, rawHeadersInit); + } + return headers; + } + }) + }); + Headers.prototype.set = new Proxy(Headers.prototype.set, { + apply(target, thisArg, args) { + recordRawHeader(thisArg, args, "set"); + return Reflect.apply(target, thisArg, args); + } + }); + Headers.prototype.append = new Proxy(Headers.prototype.append, { + apply(target, thisArg, args) { + recordRawHeader(thisArg, args, "append"); + return Reflect.apply(target, thisArg, args); + } + }); + Headers.prototype.delete = new Proxy(Headers.prototype.delete, { + apply(target, thisArg, args) { + const rawHeaders = Reflect.get(thisArg, kRawHeaders); + if (rawHeaders) { + for (let index = rawHeaders.length - 1; index >= 0; index--) { + if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) { + rawHeaders.splice(index, 1); + } + } + } + return Reflect.apply(target, thisArg, args); + } + }); + Object.defineProperty(globalThis, "Request", { + enumerable: true, + writable: true, + value: new Proxy(Request, { + construct(target, args, newTarget) { + const request = Reflect.construct(target, args, newTarget); + const inferredRawHeaders = []; + if (typeof args[0] === "object" && args[0].headers != null) { + inferredRawHeaders.push(...inferRawHeaders(args[0].headers)); + } + if (typeof args[1] === "object" && args[1].headers != null) { + inferredRawHeaders.push(...inferRawHeaders(args[1].headers)); + } + if (inferredRawHeaders.length > 0) { + ensureRawHeadersSymbol(request.headers, inferredRawHeaders); + } + return request; + } + }) + }); + Object.defineProperty(globalThis, "Response", { + enumerable: true, + writable: true, + value: new Proxy(Response, { + construct(target, args, newTarget) { + const response = Reflect.construct(target, args, newTarget); + if (typeof args[1] === "object" && args[1].headers != null) { + ensureRawHeadersSymbol( + response.headers, + inferRawHeaders(args[1].headers) + ); + } + return response; + } + }) + }); +} +function restoreHeadersPrototype() { + if (!Reflect.get(Headers, kRestorePatches)) { + return; + } + Reflect.get(Headers, kRestorePatches)(); +} +function getRawFetchHeaders(headers) { + if (!Reflect.has(headers, kRawHeaders)) { + return Array.from(headers.entries()); + } + const rawHeaders = Reflect.get(headers, kRawHeaders); + return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries()); +} +function inferRawHeaders(headers) { + if (headers instanceof Headers) { + return Reflect.get(headers, kRawHeaders) || []; + } + return Reflect.get(new Headers(headers), kRawHeaders); +} + +// src/interceptors/ClientRequest/MockHttpSocket.ts +var kRequestId = Symbol("kRequestId"); +var MockHttpSocket = class extends MockSocket { + constructor(options) { + super({ + write: (chunk, encoding, callback) => { + var _a; + if (this.socketState !== "passthrough") { + this.writeBuffer.push([chunk, encoding, callback]); + } + if (chunk) { + if (this.socketState === "passthrough") { + (_a = this.originalSocket) == null ? void 0 : _a.write(chunk, encoding, callback); + } + this.requestParser.execute( + Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding) + ); + } + }, + read: (chunk) => { + if (chunk !== null) { + this.responseParser.execute( + Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk) + ); + } + } + }); + this.writeBuffer = []; + this.socketState = "unknown"; + this.onRequestStart = (versionMajor, versionMinor, rawHeaders, _, path, __, ___, ____, shouldKeepAlive) => { + var _a; + this.shouldKeepAlive = shouldKeepAlive; + const url = new URL(path, this.baseUrl); + const method = ((_a = this.connectionOptions.method) == null ? void 0 : _a.toUpperCase()) || "GET"; + const headers = FetchResponse.parseRawHeaders(rawHeaders); + const canHaveBody = method !== "GET" && method !== "HEAD"; + if (url.username || url.password) { + if (!headers.has("authorization")) { + headers.set("authorization", `Basic ${url.username}:${url.password}`); + } + url.username = ""; + url.password = ""; + } + if (canHaveBody) { + this.requestStream = new Readable({ + /** + * @note Provide the `read()` method so a `Readable` could be + * used as the actual request body (the stream calls "read()"). + * We control the queue in the onRequestBody/End functions. + */ + read: () => { + this.flushWriteBuffer(); + } + }); + } + const requestId = createRequestId(); + this.request = new Request(url, { + method, + headers, + credentials: "same-origin", + // @ts-expect-error Undocumented Fetch property. + duplex: canHaveBody ? "half" : void 0, + body: canHaveBody ? Readable.toWeb(this.requestStream) : null + }); + Reflect.set(this.request, kRequestId, requestId); + if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) { + this.passthrough(); + return; + } + this.onRequest({ + requestId, + request: this.request, + socket: this + }); + }; + this.onResponseStart = (versionMajor, versionMinor, rawHeaders, method, url, status, statusText) => { + const headers = FetchResponse.parseRawHeaders(rawHeaders); + const response = new FetchResponse( + /** + * @note The Fetch API response instance exposed to the consumer + * is created over the response stream of the HTTP parser. It is NOT + * related to the Socket instance. This way, you can read response body + * in response listener while the Socket instance delays the emission + * of "end" and other events until those response listeners are finished. + */ + FetchResponse.isResponseWithBody(status) ? Readable.toWeb( + this.responseStream = new Readable({ read() { + } }) + ) : null, + { + url, + status, + statusText, + headers + } + ); + invariant( + this.request, + "Failed to handle a response: request does not exist" + ); + if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) { + return; + } + this.responseListenersPromise = this.onResponse({ + response, + isMockedResponse: this.socketState === "mock", + requestId: Reflect.get(this.request, kRequestId), + request: this.request, + socket: this + }); + }; + this.connectionOptions = options.connectionOptions; + this.createConnection = options.createConnection; + this.onRequest = options.onRequest; + this.onResponse = options.onResponse; + this.baseUrl = baseUrlFromConnectionOptions(this.connectionOptions); + this.requestParser = new HTTPParser(); + this.requestParser.initialize(HTTPParser.REQUEST, {}); + this.requestParser[HTTPParser.kOnHeadersComplete] = this.onRequestStart.bind(this); + this.requestParser[HTTPParser.kOnBody] = this.onRequestBody.bind(this); + this.requestParser[HTTPParser.kOnMessageComplete] = this.onRequestEnd.bind(this); + this.responseParser = new HTTPParser(); + this.responseParser.initialize(HTTPParser.RESPONSE, {}); + this.responseParser[HTTPParser.kOnHeadersComplete] = this.onResponseStart.bind(this); + this.responseParser[HTTPParser.kOnBody] = this.onResponseBody.bind(this); + this.responseParser[HTTPParser.kOnMessageComplete] = this.onResponseEnd.bind(this); + this.once("finish", () => this.requestParser.free()); + if (this.baseUrl.protocol === "https:") { + Reflect.set(this, "encrypted", true); + Reflect.set(this, "authorized", false); + Reflect.set(this, "getProtocol", () => "TLSv1.3"); + Reflect.set(this, "getSession", () => void 0); + Reflect.set(this, "isSessionReused", () => false); + } + } + emit(event, ...args) { + const emitEvent = super.emit.bind(this, event, ...args); + if (this.responseListenersPromise) { + this.responseListenersPromise.finally(emitEvent); + return this.listenerCount(event) > 0; + } + return emitEvent(); + } + destroy(error) { + this.responseParser.free(); + if (error) { + this.emit("error", error); + } + return super.destroy(error); + } + /** + * Establish this Socket connection as-is and pipe + * its data/events through this Socket. + */ + passthrough() { + this.socketState = "passthrough"; + if (this.destroyed) { + return; + } + const socket = this.createConnection(); + this.originalSocket = socket; + this.once("error", (error) => { + socket.destroy(error); + }); + this.address = socket.address.bind(socket); + let writeArgs; + let headersWritten = false; + while (writeArgs = this.writeBuffer.shift()) { + if (writeArgs !== void 0) { + if (!headersWritten) { + const [chunk, encoding, callback] = writeArgs; + const chunkString = chunk.toString(); + const chunkBeforeRequestHeaders = chunkString.slice( + 0, + chunkString.indexOf("\r\n") + 2 + ); + const chunkAfterRequestHeaders = chunkString.slice( + chunk.indexOf("\r\n\r\n") + ); + const rawRequestHeaders = getRawFetchHeaders(this.request.headers); + const requestHeadersString = rawRequestHeaders.filter(([name]) => { + return name.toLowerCase() !== INTERNAL_REQUEST_ID_HEADER_NAME; + }).map(([name, value]) => `${name}: ${value}`).join("\r\n"); + const headersChunk = `${chunkBeforeRequestHeaders}${requestHeadersString}${chunkAfterRequestHeaders}`; + socket.write(headersChunk, encoding, callback); + headersWritten = true; + continue; + } + socket.write(...writeArgs); + } + } + if (Reflect.get(socket, "encrypted")) { + const tlsProperties = [ + "encrypted", + "authorized", + "getProtocol", + "getSession", + "isSessionReused" + ]; + tlsProperties.forEach((propertyName) => { + Object.defineProperty(this, propertyName, { + enumerable: true, + get: () => { + const value = Reflect.get(socket, propertyName); + return typeof value === "function" ? value.bind(socket) : value; + } + }); + }); + } + socket.on("lookup", (...args) => this.emit("lookup", ...args)).on("connect", () => { + this.connecting = socket.connecting; + this.emit("connect"); + }).on("secureConnect", () => this.emit("secureConnect")).on("secure", () => this.emit("secure")).on("session", (session) => this.emit("session", session)).on("ready", () => this.emit("ready")).on("drain", () => this.emit("drain")).on("data", (chunk) => { + this.push(chunk); + }).on("error", (error) => { + Reflect.set(this, "_hadError", Reflect.get(socket, "_hadError")); + this.emit("error", error); + }).on("resume", () => this.emit("resume")).on("timeout", () => this.emit("timeout")).on("prefinish", () => this.emit("prefinish")).on("finish", () => this.emit("finish")).on("close", (hadError) => this.emit("close", hadError)).on("end", () => this.emit("end")); + } + /** + * Convert the given Fetch API `Response` instance to an + * HTTP message and push it to the socket. + */ + async respondWith(response) { + var _a; + if (this.destroyed) { + return; + } + if (isPropertyAccessible(response, "type") && response.type === "error") { + this.errorWith(new TypeError("Network error")); + return; + } + this.mockConnect(); + this.socketState = "mock"; + this.flushWriteBuffer(); + const serverResponse = new ServerResponse(new IncomingMessage(this)); + serverResponse.assignSocket( + new MockSocket({ + write: (chunk, encoding, callback) => { + this.push(chunk, encoding); + callback == null ? void 0 : callback(); + }, + read() { + } + }) + ); + serverResponse.removeHeader("connection"); + serverResponse.removeHeader("date"); + const rawResponseHeaders = getRawFetchHeaders(response.headers); + serverResponse.writeHead( + response.status, + response.statusText || STATUS_CODES[response.status], + rawResponseHeaders + ); + this.once("error", () => { + serverResponse.destroy(); + }); + if (response.body) { + try { + const reader = response.body.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + serverResponse.end(); + break; + } + serverResponse.write(value); + } + } catch (error) { + this.respondWith(createServerErrorResponse(error)); + return; + } + } else { + serverResponse.end(); + } + if (!this.shouldKeepAlive) { + this.emit("readable"); + (_a = this.responseStream) == null ? void 0 : _a.push(null); + this.push(null); + } + } + /** + * Close this socket connection with the given error. + */ + errorWith(error) { + this.destroy(error); + } + mockConnect() { + this.connecting = false; + const isIPv6 = net2.isIPv6(this.connectionOptions.hostname) || this.connectionOptions.family === 6; + const addressInfo = { + address: isIPv6 ? "::1" : "127.0.0.1", + family: isIPv6 ? "IPv6" : "IPv4", + port: this.connectionOptions.port + }; + this.address = () => addressInfo; + this.emit( + "lookup", + null, + addressInfo.address, + addressInfo.family === "IPv6" ? 6 : 4, + this.connectionOptions.host + ); + this.emit("connect"); + this.emit("ready"); + if (this.baseUrl.protocol === "https:") { + this.emit("secure"); + this.emit("secureConnect"); + this.emit( + "session", + this.connectionOptions.session || Buffer.from("mock-session-renegotiate") + ); + this.emit("session", Buffer.from("mock-session-resume")); + } + } + flushWriteBuffer() { + for (const writeCall of this.writeBuffer) { + if (typeof writeCall[2] === "function") { + writeCall[2](); + writeCall[2] = void 0; + } + } + } + onRequestBody(chunk) { + invariant( + this.requestStream, + "Failed to write to a request stream: stream does not exist" + ); + this.requestStream.push(chunk); + } + onRequestEnd() { + if (this.requestStream) { + this.requestStream.push(null); + } + } + onResponseBody(chunk) { + invariant( + this.responseStream, + "Failed to write to a response stream: stream does not exist" + ); + this.responseStream.push(chunk); + } + onResponseEnd() { + if (this.responseStream) { + this.responseStream.push(null); + } + } +}; + +// src/interceptors/ClientRequest/agents.ts +import http from "http"; +import https from "https"; +var MockAgent = class extends http.Agent { + constructor(options) { + super(); + this.customAgent = options.customAgent; + this.onRequest = options.onRequest; + this.onResponse = options.onResponse; + } + createConnection(options, callback) { + const createConnection = this.customAgent instanceof http.Agent && this.customAgent.createConnection || super.createConnection; + const socket = new MockHttpSocket({ + connectionOptions: options, + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), + onRequest: this.onRequest.bind(this), + onResponse: this.onResponse.bind(this) + }); + return socket; + } +}; +var MockHttpsAgent = class extends https.Agent { + constructor(options) { + super(); + this.customAgent = options.customAgent; + this.onRequest = options.onRequest; + this.onResponse = options.onResponse; + } + createConnection(options, callback) { + const createConnection = this.customAgent instanceof https.Agent && this.customAgent.createConnection || super.createConnection; + const socket = new MockHttpSocket({ + connectionOptions: options, + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), + onRequest: this.onRequest.bind(this), + onResponse: this.onResponse.bind(this) + }); + return socket; + } +}; + +// src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +import { urlToHttpOptions } from "url"; +import { + Agent as HttpAgent, + globalAgent as httpGlobalAgent +} from "http"; +import { + Agent as HttpsAgent, + globalAgent as httpsGlobalAgent +} from "https"; +import { + URL as URL2, + parse as parseUrl +} from "url"; +import { Logger as Logger3 } from "@open-draft/logger"; + +// src/utils/getUrlByRequestOptions.ts +import { Agent } from "http"; +import { Logger } from "@open-draft/logger"; +var logger = new Logger("utils getUrlByRequestOptions"); +var DEFAULT_PATH = "/"; +var DEFAULT_PROTOCOL = "http:"; +var DEFAULT_HOSTNAME = "localhost"; +var SSL_PORT = 443; +function getAgent(options) { + return options.agent instanceof Agent ? options.agent : void 0; +} +function getProtocolByRequestOptions(options) { + var _a; + if (options.protocol) { + return options.protocol; + } + const agent = getAgent(options); + const agentProtocol = agent == null ? void 0 : agent.protocol; + if (agentProtocol) { + return agentProtocol; + } + const port = getPortByRequestOptions(options); + const isSecureRequest = options.cert || port === SSL_PORT; + return isSecureRequest ? "https:" : ((_a = options.uri) == null ? void 0 : _a.protocol) || DEFAULT_PROTOCOL; +} +function getPortByRequestOptions(options) { + if (options.port) { + return Number(options.port); + } + const agent = getAgent(options); + if (agent == null ? void 0 : agent.options.port) { + return Number(agent.options.port); + } + if (agent == null ? void 0 : agent.defaultPort) { + return Number(agent.defaultPort); + } + return void 0; +} +function getAuthByRequestOptions(options) { + if (options.auth) { + const [username, password] = options.auth.split(":"); + return { username, password }; + } +} +function isRawIPv6Address(host) { + return host.includes(":") && !host.startsWith("[") && !host.endsWith("]"); +} +function getHostname(options) { + let host = options.hostname || options.host; + if (host) { + if (isRawIPv6Address(host)) { + host = `[${host}]`; + } + return new URL(`http://${host}`).hostname; + } + return DEFAULT_HOSTNAME; +} +function getUrlByRequestOptions(options) { + logger.info("request options", options); + if (options.uri) { + logger.info( + 'constructing url from explicitly provided "options.uri": %s', + options.uri + ); + return new URL(options.uri.href); + } + logger.info("figuring out url from request options..."); + const protocol = getProtocolByRequestOptions(options); + logger.info("protocol", protocol); + const port = getPortByRequestOptions(options); + logger.info("port", port); + const hostname = getHostname(options); + logger.info("hostname", hostname); + const path = options.path || DEFAULT_PATH; + logger.info("path", path); + const credentials = getAuthByRequestOptions(options); + logger.info("credentials", credentials); + const authString = credentials ? `${credentials.username}:${credentials.password}@` : ""; + logger.info("auth string:", authString); + const portString = typeof port !== "undefined" ? `:${port}` : ""; + const url = new URL(`${protocol}//${hostname}${portString}${path}`); + url.username = (credentials == null ? void 0 : credentials.username) || ""; + url.password = (credentials == null ? void 0 : credentials.password) || ""; + logger.info("created url:", url); + return url; +} + +// src/utils/cloneObject.ts +import { Logger as Logger2 } from "@open-draft/logger"; +var logger2 = new Logger2("cloneObject"); +function isPlainObject(obj) { + var _a; + logger2.info("is plain object?", obj); + if (obj == null || !((_a = obj.constructor) == null ? void 0 : _a.name)) { + logger2.info("given object is undefined, not a plain object..."); + return false; + } + logger2.info("checking the object constructor:", obj.constructor.name); + return obj.constructor.name === "Object"; +} +function cloneObject(obj) { + logger2.info("cloning object:", obj); + const enumerableProperties = Object.entries(obj).reduce( + (acc, [key, value]) => { + logger2.info("analyzing key-value pair:", key, value); + acc[key] = isPlainObject(value) ? cloneObject(value) : value; + return acc; + }, + {} + ); + return isPlainObject(obj) ? enumerableProperties : Object.assign(Object.getPrototypeOf(obj), enumerableProperties); +} + +// src/utils/isObject.ts +function isObject(value, loose = false) { + return loose ? Object.prototype.toString.call(value).startsWith("[object ") : Object.prototype.toString.call(value) === "[object Object]"; +} + +// src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +var logger3 = new Logger3("http normalizeClientRequestArgs"); +function resolveRequestOptions(args, url) { + if (typeof args[1] === "undefined" || typeof args[1] === "function") { + logger3.info("request options not provided, deriving from the url", url); + return urlToHttpOptions(url); + } + if (args[1]) { + logger3.info("has custom RequestOptions!", args[1]); + const requestOptionsFromUrl = urlToHttpOptions(url); + logger3.info("derived RequestOptions from the URL:", requestOptionsFromUrl); + logger3.info("cloning RequestOptions..."); + const clonedRequestOptions = cloneObject(args[1]); + logger3.info("successfully cloned RequestOptions!", clonedRequestOptions); + return { + ...requestOptionsFromUrl, + ...clonedRequestOptions + }; + } + logger3.info("using an empty object as request options"); + return {}; +} +function overrideUrlByRequestOptions(url, options) { + url.host = options.host || url.host; + url.hostname = options.hostname || url.hostname; + url.port = options.port ? options.port.toString() : url.port; + if (options.path) { + const parsedOptionsPath = parseUrl(options.path, false); + url.pathname = parsedOptionsPath.pathname || ""; + url.search = parsedOptionsPath.search || ""; + } + return url; +} +function resolveCallback(args) { + return typeof args[1] === "function" ? args[1] : args[2]; +} +function normalizeClientRequestArgs(defaultProtocol, args) { + let url; + let options; + let callback; + logger3.info("arguments", args); + logger3.info("using default protocol:", defaultProtocol); + if (args.length === 0) { + const url2 = new URL2("http://localhost"); + const options2 = resolveRequestOptions(args, url2); + return [url2, options2]; + } + if (typeof args[0] === "string") { + logger3.info("first argument is a location string:", args[0]); + url = new URL2(args[0]); + logger3.info("created a url:", url); + const requestOptionsFromUrl = urlToHttpOptions(url); + logger3.info("request options from url:", requestOptionsFromUrl); + options = resolveRequestOptions(args, url); + logger3.info("resolved request options:", options); + callback = resolveCallback(args); + } else if (args[0] instanceof URL2) { + url = args[0]; + logger3.info("first argument is a URL:", url); + if (typeof args[1] !== "undefined" && isObject(args[1])) { + url = overrideUrlByRequestOptions(url, args[1]); + } + options = resolveRequestOptions(args, url); + logger3.info("derived request options:", options); + callback = resolveCallback(args); + } else if ("hash" in args[0] && !("method" in args[0])) { + const [legacyUrl] = args; + logger3.info("first argument is a legacy URL:", legacyUrl); + if (legacyUrl.hostname === null) { + logger3.info("given legacy URL is relative (no hostname)"); + return isObject(args[1]) ? normalizeClientRequestArgs(defaultProtocol, [ + { path: legacyUrl.path, ...args[1] }, + args[2] + ]) : normalizeClientRequestArgs(defaultProtocol, [ + { path: legacyUrl.path }, + args[1] + ]); + } + logger3.info("given legacy url is absolute"); + const resolvedUrl = new URL2(legacyUrl.href); + return args[1] === void 0 ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl]) : typeof args[1] === "function" ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl, args[1]]) : normalizeClientRequestArgs(defaultProtocol, [ + resolvedUrl, + args[1], + args[2] + ]); + } else if (isObject(args[0])) { + options = { ...args[0] }; + logger3.info("first argument is RequestOptions:", options); + options.protocol = options.protocol || defaultProtocol; + logger3.info("normalized request options:", options); + url = getUrlByRequestOptions(options); + logger3.info("created a URL from RequestOptions:", url.href); + callback = resolveCallback(args); + } else { + throw new Error( + `Failed to construct ClientRequest with these parameters: ${args}` + ); + } + options.protocol = options.protocol || url.protocol; + options.method = options.method || "GET"; + if (typeof options.agent === "undefined") { + const agent = options.protocol === "https:" ? new HttpsAgent({ + rejectUnauthorized: options.rejectUnauthorized + }) : new HttpAgent(); + options.agent = agent; + logger3.info("resolved fallback agent:", agent); + } + if (!options._defaultAgent) { + logger3.info( + 'has no default agent, setting the default agent for "%s"', + options.protocol + ); + options._defaultAgent = options.protocol === "https:" ? httpsGlobalAgent : httpGlobalAgent; + } + logger3.info("successfully resolved url:", url.href); + logger3.info("successfully resolved options:", options); + logger3.info("successfully resolved callback:", callback); + if (!(url instanceof URL2)) { + url = url.toString(); + } + return [url, options, callback]; +} + +// src/interceptors/ClientRequest/index.ts +var _ClientRequestInterceptor = class extends Interceptor { + constructor() { + super(_ClientRequestInterceptor.symbol); + this.onRequest = async ({ + request, + socket + }) => { + const requestId = Reflect.get(request, kRequestId); + const controller = new RequestController(request); + const isRequestHandled = await handleRequest({ + request, + requestId, + controller, + emitter: this.emitter, + onResponse: (response) => { + socket.respondWith(response); + }, + onRequestError: (response) => { + socket.respondWith(response); + }, + onError: (error) => { + if (error instanceof Error) { + socket.errorWith(error); + } + } + }); + if (!isRequestHandled) { + return socket.passthrough(); + } + }; + this.onResponse = async ({ + requestId, + request, + response, + isMockedResponse + }) => { + return emitAsync(this.emitter, "response", { + requestId, + request, + response, + isMockedResponse + }); + }; + } + setup() { + const { get: originalGet, request: originalRequest } = http2; + const { get: originalHttpsGet, request: originalHttpsRequest } = https2; + const onRequest = this.onRequest.bind(this); + const onResponse = this.onResponse.bind(this); + http2.request = new Proxy(http2.request, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "http:", + args + ); + const mockAgent = new MockAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + http2.get = new Proxy(http2.get, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "http:", + args + ); + const mockAgent = new MockAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + https2.request = new Proxy(https2.request, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "https:", + args + ); + const mockAgent = new MockHttpsAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + https2.get = new Proxy(https2.get, { + apply: (target, thisArg, args) => { + const [url, options, callback] = normalizeClientRequestArgs( + "https:", + args + ); + const mockAgent = new MockHttpsAgent({ + customAgent: options.agent, + onRequest, + onResponse + }); + options.agent = mockAgent; + return Reflect.apply(target, thisArg, [url, options, callback]); + } + }); + recordRawFetchHeaders(); + this.subscriptions.push(() => { + http2.get = originalGet; + http2.request = originalRequest; + https2.get = originalHttpsGet; + https2.request = originalHttpsRequest; + restoreHeadersPrototype(); + }); + } +}; +var ClientRequestInterceptor = _ClientRequestInterceptor; +ClientRequestInterceptor.symbol = Symbol("client-request-interceptor"); + +export { + ClientRequestInterceptor +}; +//# sourceMappingURL=chunk-QFFDMWKW.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-QFFDMWKW.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-QFFDMWKW.mjs.map new file mode 100644 index 0000000000..84cadf1c59 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-QFFDMWKW.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/interceptors/ClientRequest/index.ts","../../src/interceptors/ClientRequest/MockHttpSocket.ts","../../src/interceptors/Socket/MockSocket.ts","../../src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts","../../src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts","../../src/interceptors/ClientRequest/utils/recordRawHeaders.ts","../../src/interceptors/ClientRequest/agents.ts","../../src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts","../../src/utils/getUrlByRequestOptions.ts","../../src/utils/cloneObject.ts","../../src/utils/isObject.ts"],"sourcesContent":["import http from 'node:http'\nimport https from 'node:https'\nimport { Interceptor } from '../../Interceptor'\nimport type { HttpRequestEventMap } from '../../glossary'\nimport {\n kRequestId,\n MockHttpSocketRequestCallback,\n MockHttpSocketResponseCallback,\n} from './MockHttpSocket'\nimport { MockAgent, MockHttpsAgent } from './agents'\nimport { RequestController } from '../../RequestController'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { normalizeClientRequestArgs } from './utils/normalizeClientRequestArgs'\nimport { handleRequest } from '../../utils/handleRequest'\nimport {\n recordRawFetchHeaders,\n restoreHeadersPrototype,\n} from './utils/recordRawHeaders'\n\nexport class ClientRequestInterceptor extends Interceptor {\n static symbol = Symbol('client-request-interceptor')\n\n constructor() {\n super(ClientRequestInterceptor.symbol)\n }\n\n protected setup(): void {\n const { get: originalGet, request: originalRequest } = http\n const { get: originalHttpsGet, request: originalHttpsRequest } = https\n\n const onRequest = this.onRequest.bind(this)\n const onResponse = this.onResponse.bind(this)\n\n http.request = new Proxy(http.request, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'http:',\n args\n )\n const mockAgent = new MockAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n http.get = new Proxy(http.get, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'http:',\n args\n )\n\n const mockAgent = new MockAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n //\n // HTTPS.\n //\n\n https.request = new Proxy(https.request, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'https:',\n args\n )\n\n const mockAgent = new MockHttpsAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n https.get = new Proxy(https.get, {\n apply: (target, thisArg, args: Parameters) => {\n const [url, options, callback] = normalizeClientRequestArgs(\n 'https:',\n args\n )\n\n const mockAgent = new MockHttpsAgent({\n customAgent: options.agent,\n onRequest,\n onResponse,\n })\n options.agent = mockAgent\n\n return Reflect.apply(target, thisArg, [url, options, callback])\n },\n })\n\n // Spy on `Header.prototype.set` and `Header.prototype.append` calls\n // and record the raw header names provided. This is to support\n // `IncomingMessage.prototype.rawHeaders`.\n recordRawFetchHeaders()\n\n this.subscriptions.push(() => {\n http.get = originalGet\n http.request = originalRequest\n\n https.get = originalHttpsGet\n https.request = originalHttpsRequest\n\n restoreHeadersPrototype()\n })\n }\n\n private onRequest: MockHttpSocketRequestCallback = async ({\n request,\n socket,\n }) => {\n const requestId = Reflect.get(request, kRequestId)\n const controller = new RequestController(request)\n\n const isRequestHandled = await handleRequest({\n request,\n requestId,\n controller,\n emitter: this.emitter,\n onResponse: (response) => {\n socket.respondWith(response)\n },\n onRequestError: (response) => {\n socket.respondWith(response)\n },\n onError: (error) => {\n if (error instanceof Error) {\n socket.errorWith(error)\n }\n },\n })\n\n if (!isRequestHandled) {\n return socket.passthrough()\n }\n }\n\n public onResponse: MockHttpSocketResponseCallback = async ({\n requestId,\n request,\n response,\n isMockedResponse,\n }) => {\n // Return the promise to when all the response event listeners\n // are finished.\n return emitAsync(this.emitter, 'response', {\n requestId,\n request,\n response,\n isMockedResponse,\n })\n }\n}\n","import net from 'node:net'\nimport {\n HTTPParser,\n type RequestHeadersCompleteCallback,\n type ResponseHeadersCompleteCallback,\n} from '_http_common'\nimport { STATUS_CODES, IncomingMessage, ServerResponse } from 'node:http'\nimport { Readable } from 'node:stream'\nimport { invariant } from 'outvariant'\nimport { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'\nimport { MockSocket } from '../Socket/MockSocket'\nimport type { NormalizedSocketWriteArgs } from '../Socket/utils/normalizeSocketWriteArgs'\nimport { isPropertyAccessible } from '../../utils/isPropertyAccessible'\nimport { baseUrlFromConnectionOptions } from '../Socket/utils/baseUrlFromConnectionOptions'\nimport { createServerErrorResponse } from '../../utils/responseUtils'\nimport { createRequestId } from '../../createRequestId'\nimport { getRawFetchHeaders } from './utils/recordRawHeaders'\nimport { FetchResponse } from '../../utils/fetchUtils'\n\ntype HttpConnectionOptions = any\n\nexport type MockHttpSocketRequestCallback = (args: {\n requestId: string\n request: Request\n socket: MockHttpSocket\n}) => void\n\nexport type MockHttpSocketResponseCallback = (args: {\n requestId: string\n request: Request\n response: Response\n isMockedResponse: boolean\n socket: MockHttpSocket\n}) => Promise\n\ninterface MockHttpSocketOptions {\n connectionOptions: HttpConnectionOptions\n createConnection: () => net.Socket\n onRequest: MockHttpSocketRequestCallback\n onResponse: MockHttpSocketResponseCallback\n}\n\nexport const kRequestId = Symbol('kRequestId')\n\nexport class MockHttpSocket extends MockSocket {\n private connectionOptions: HttpConnectionOptions\n private createConnection: () => net.Socket\n private baseUrl: URL\n\n private onRequest: MockHttpSocketRequestCallback\n private onResponse: MockHttpSocketResponseCallback\n private responseListenersPromise?: Promise\n\n private writeBuffer: Array = []\n private request?: Request\n private requestParser: HTTPParser<0>\n private requestStream?: Readable\n private shouldKeepAlive?: boolean\n\n private socketState: 'unknown' | 'mock' | 'passthrough' = 'unknown'\n private responseParser: HTTPParser<1>\n private responseStream?: Readable\n private originalSocket?: net.Socket\n\n constructor(options: MockHttpSocketOptions) {\n super({\n write: (chunk, encoding, callback) => {\n // Buffer the writes so they can be flushed in case of the original connection\n // and when reading the request body in the interceptor. If the connection has\n // been established, no need to buffer the chunks anymore, they will be forwarded.\n if (this.socketState !== 'passthrough') {\n this.writeBuffer.push([chunk, encoding, callback])\n }\n\n if (chunk) {\n /**\n * Forward any writes to the mock socket to the underlying original socket.\n * This ensures functional duplex connections, like WebSocket.\n * @see https://github.com/mswjs/interceptors/issues/682\n */\n if (this.socketState === 'passthrough') {\n this.originalSocket?.write(chunk, encoding, callback)\n }\n\n this.requestParser.execute(\n Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding)\n )\n }\n },\n read: (chunk) => {\n if (chunk !== null) {\n /**\n * @todo We need to free the parser if the connection has been\n * upgraded to a non-HTTP protocol. It won't be able to parse data\n * from that point onward anyway. No need to keep it in memory.\n */\n this.responseParser.execute(\n Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n )\n }\n },\n })\n\n this.connectionOptions = options.connectionOptions\n this.createConnection = options.createConnection\n this.onRequest = options.onRequest\n this.onResponse = options.onResponse\n\n this.baseUrl = baseUrlFromConnectionOptions(this.connectionOptions)\n\n // Request parser.\n this.requestParser = new HTTPParser()\n this.requestParser.initialize(HTTPParser.REQUEST, {})\n this.requestParser[HTTPParser.kOnHeadersComplete] =\n this.onRequestStart.bind(this)\n this.requestParser[HTTPParser.kOnBody] = this.onRequestBody.bind(this)\n this.requestParser[HTTPParser.kOnMessageComplete] =\n this.onRequestEnd.bind(this)\n\n // Response parser.\n this.responseParser = new HTTPParser()\n this.responseParser.initialize(HTTPParser.RESPONSE, {})\n this.responseParser[HTTPParser.kOnHeadersComplete] =\n this.onResponseStart.bind(this)\n this.responseParser[HTTPParser.kOnBody] = this.onResponseBody.bind(this)\n this.responseParser[HTTPParser.kOnMessageComplete] =\n this.onResponseEnd.bind(this)\n\n // Once the socket is finished, nothing can write to it\n // anymore. It has also flushed any buffered chunks.\n this.once('finish', () => this.requestParser.free())\n\n if (this.baseUrl.protocol === 'https:') {\n Reflect.set(this, 'encrypted', true)\n // The server certificate is not the same as a CA\n // passed to the TLS socket connection options.\n Reflect.set(this, 'authorized', false)\n Reflect.set(this, 'getProtocol', () => 'TLSv1.3')\n Reflect.set(this, 'getSession', () => undefined)\n Reflect.set(this, 'isSessionReused', () => false)\n }\n }\n\n public emit(event: string | symbol, ...args: any[]): boolean {\n const emitEvent = super.emit.bind(this, event as any, ...args)\n\n if (this.responseListenersPromise) {\n this.responseListenersPromise.finally(emitEvent)\n return this.listenerCount(event) > 0\n }\n\n return emitEvent()\n }\n\n public destroy(error?: Error | undefined): this {\n // Destroy the response parser when the socket gets destroyed.\n // Normally, we shoud listen to the \"close\" event but it\n // can be suppressed by using the \"emitClose: false\" option.\n this.responseParser.free()\n\n if (error) {\n this.emit('error', error)\n }\n\n return super.destroy(error)\n }\n\n /**\n * Establish this Socket connection as-is and pipe\n * its data/events through this Socket.\n */\n public passthrough(): void {\n this.socketState = 'passthrough'\n\n if (this.destroyed) {\n return\n }\n\n const socket = this.createConnection()\n this.originalSocket = socket\n\n // If the developer destroys the socket, destroy the original connection.\n this.once('error', (error) => {\n socket.destroy(error)\n })\n\n this.address = socket.address.bind(socket)\n\n // Flush the buffered \"socket.write()\" calls onto\n // the original socket instance (i.e. write request body).\n // Exhaust the \"requestBuffer\" in case this Socket\n // gets reused for different requests.\n let writeArgs: NormalizedSocketWriteArgs | undefined\n let headersWritten = false\n\n while ((writeArgs = this.writeBuffer.shift())) {\n if (writeArgs !== undefined) {\n if (!headersWritten) {\n const [chunk, encoding, callback] = writeArgs\n const chunkString = chunk.toString()\n const chunkBeforeRequestHeaders = chunkString.slice(\n 0,\n chunkString.indexOf('\\r\\n') + 2\n )\n const chunkAfterRequestHeaders = chunkString.slice(\n chunk.indexOf('\\r\\n\\r\\n')\n )\n const rawRequestHeaders = getRawFetchHeaders(this.request!.headers)\n const requestHeadersString = rawRequestHeaders\n // Skip the internal request ID deduplication header.\n .filter(([name]) => {\n return name.toLowerCase() !== INTERNAL_REQUEST_ID_HEADER_NAME\n })\n .map(([name, value]) => `${name}: ${value}`)\n .join('\\r\\n')\n\n // Modify the HTTP request message headers\n // to reflect any changes to the request headers\n // from the \"request\" event listener.\n const headersChunk = `${chunkBeforeRequestHeaders}${requestHeadersString}${chunkAfterRequestHeaders}`\n socket.write(headersChunk, encoding, callback)\n headersWritten = true\n continue\n }\n\n socket.write(...writeArgs)\n }\n }\n\n // Forward TLS Socket properties onto this Socket instance\n // in the case of a TLS/SSL connection.\n if (Reflect.get(socket, 'encrypted')) {\n const tlsProperties = [\n 'encrypted',\n 'authorized',\n 'getProtocol',\n 'getSession',\n 'isSessionReused',\n ]\n\n tlsProperties.forEach((propertyName) => {\n Object.defineProperty(this, propertyName, {\n enumerable: true,\n get: () => {\n const value = Reflect.get(socket, propertyName)\n return typeof value === 'function' ? value.bind(socket) : value\n },\n })\n })\n }\n\n socket\n .on('lookup', (...args) => this.emit('lookup', ...args))\n .on('connect', () => {\n this.connecting = socket.connecting\n this.emit('connect')\n })\n .on('secureConnect', () => this.emit('secureConnect'))\n .on('secure', () => this.emit('secure'))\n .on('session', (session) => this.emit('session', session))\n .on('ready', () => this.emit('ready'))\n .on('drain', () => this.emit('drain'))\n .on('data', (chunk) => {\n // Push the original response to this socket\n // so it triggers the HTTP response parser. This unifies\n // the handling pipeline for original and mocked response.\n this.push(chunk)\n })\n .on('error', (error) => {\n Reflect.set(this, '_hadError', Reflect.get(socket, '_hadError'))\n this.emit('error', error)\n })\n .on('resume', () => this.emit('resume'))\n .on('timeout', () => this.emit('timeout'))\n .on('prefinish', () => this.emit('prefinish'))\n .on('finish', () => this.emit('finish'))\n .on('close', (hadError) => this.emit('close', hadError))\n .on('end', () => this.emit('end'))\n }\n\n /**\n * Convert the given Fetch API `Response` instance to an\n * HTTP message and push it to the socket.\n */\n public async respondWith(response: Response): Promise {\n // Ignore the mocked response if the socket has been destroyed\n // (e.g. aborted or timed out),\n if (this.destroyed) {\n return\n }\n\n // Handle \"type: error\" responses.\n if (isPropertyAccessible(response, 'type') && response.type === 'error') {\n this.errorWith(new TypeError('Network error'))\n return\n }\n\n // First, emit all the connection events\n // to emulate a successful connection.\n this.mockConnect()\n this.socketState = 'mock'\n\n // Flush the write buffer to trigger write callbacks\n // if it hasn't been flushed already (e.g. someone started reading request stream).\n this.flushWriteBuffer()\n\n // Create a `ServerResponse` instance to delegate HTTP message parsing,\n // Transfer-Encoding, and other things to Node.js internals.\n const serverResponse = new ServerResponse(new IncomingMessage(this))\n\n /**\n * Assign a mock socket instance to the server response to\n * spy on the response chunk writes. Push the transformed response chunks\n * to this `MockHttpSocket` instance to trigger the \"data\" event.\n * @note Providing the same `MockSocket` instance when creating `ServerResponse`\n * does not have the same effect.\n * @see https://github.com/nodejs/node/blob/10099bb3f7fd97bb9dd9667188426866b3098e07/test/parallel/test-http-server-response-standalone.js#L32\n */\n serverResponse.assignSocket(\n new MockSocket({\n write: (chunk, encoding, callback) => {\n this.push(chunk, encoding)\n callback?.()\n },\n read() {},\n })\n )\n\n /**\n * @note Remove the `Connection` and `Date` response headers\n * injected by `ServerResponse` by default. Those are required\n * from the server but the interceptor is NOT technically a server.\n * It's confusing to add response headers that the developer didn't\n * specify themselves. They can always add these if they wish.\n * @see https://www.rfc-editor.org/rfc/rfc9110#field.date\n * @see https://www.rfc-editor.org/rfc/rfc9110#field.connection\n */\n serverResponse.removeHeader('connection')\n serverResponse.removeHeader('date')\n\n const rawResponseHeaders = getRawFetchHeaders(response.headers)\n\n /**\n * @note Call `.writeHead` in order to set the raw response headers\n * in the same case as they were provided by the developer. Using\n * `.setHeader()`/`.appendHeader()` normalizes header names.\n */\n serverResponse.writeHead(\n response.status,\n response.statusText || STATUS_CODES[response.status],\n rawResponseHeaders\n )\n\n // If the developer destroy the socket, gracefully destroy the response.\n this.once('error', () => {\n serverResponse.destroy()\n })\n\n if (response.body) {\n try {\n const reader = response.body.getReader()\n\n while (true) {\n const { done, value } = await reader.read()\n\n if (done) {\n serverResponse.end()\n break\n }\n\n serverResponse.write(value)\n }\n } catch (error) {\n // Coerce response stream errors to 500 responses.\n this.respondWith(createServerErrorResponse(error))\n return\n }\n } else {\n serverResponse.end()\n }\n\n // Close the socket if the connection wasn't marked as keep-alive.\n if (!this.shouldKeepAlive) {\n this.emit('readable')\n\n /**\n * @todo @fixme This is likely a hack.\n * Since we push null to the socket, it never propagates to the\n * parser, and the parser never calls \"onResponseEnd\" to close\n * the response stream. We are closing the stream here manually\n * but that shouldn't be the case.\n */\n this.responseStream?.push(null)\n this.push(null)\n }\n }\n\n /**\n * Close this socket connection with the given error.\n */\n public errorWith(error?: Error): void {\n this.destroy(error)\n }\n\n private mockConnect(): void {\n // Calling this method immediately puts the socket\n // into the connected state.\n this.connecting = false\n\n const isIPv6 =\n net.isIPv6(this.connectionOptions.hostname) ||\n this.connectionOptions.family === 6\n const addressInfo = {\n address: isIPv6 ? '::1' : '127.0.0.1',\n family: isIPv6 ? 'IPv6' : 'IPv4',\n port: this.connectionOptions.port,\n }\n // Return fake address information for the socket.\n this.address = () => addressInfo\n this.emit(\n 'lookup',\n null,\n addressInfo.address,\n addressInfo.family === 'IPv6' ? 6 : 4,\n this.connectionOptions.host\n )\n this.emit('connect')\n this.emit('ready')\n\n if (this.baseUrl.protocol === 'https:') {\n this.emit('secure')\n this.emit('secureConnect')\n\n // A single TLS connection is represented by two \"session\" events.\n this.emit(\n 'session',\n this.connectionOptions.session ||\n Buffer.from('mock-session-renegotiate')\n )\n this.emit('session', Buffer.from('mock-session-resume'))\n }\n }\n\n private flushWriteBuffer(): void {\n for (const writeCall of this.writeBuffer) {\n if (typeof writeCall[2] === 'function') {\n writeCall[2]()\n /**\n * @note Remove the callback from the write call\n * so it doesn't get called twice on passthrough\n * if `request.end()` was called within `request.write()`.\n * @see https://github.com/mswjs/interceptors/issues/684\n */\n writeCall[2] = undefined\n }\n }\n }\n\n private onRequestStart: RequestHeadersCompleteCallback = (\n versionMajor,\n versionMinor,\n rawHeaders,\n _,\n path,\n __,\n ___,\n ____,\n shouldKeepAlive\n ) => {\n this.shouldKeepAlive = shouldKeepAlive\n\n const url = new URL(path, this.baseUrl)\n const method = this.connectionOptions.method?.toUpperCase() || 'GET'\n const headers = FetchResponse.parseRawHeaders(rawHeaders)\n const canHaveBody = method !== 'GET' && method !== 'HEAD'\n\n // Translate the basic authorization in the URL to the request header.\n // Constructing a Request instance with a URL containing auth is no-op.\n if (url.username || url.password) {\n if (!headers.has('authorization')) {\n headers.set('authorization', `Basic ${url.username}:${url.password}`)\n }\n url.username = ''\n url.password = ''\n }\n\n // Create a new stream for each request.\n // If this Socket is reused for multiple requests,\n // this ensures that each request gets its own stream.\n // One Socket instance can only handle one request at a time.\n if (canHaveBody) {\n this.requestStream = new Readable({\n /**\n * @note Provide the `read()` method so a `Readable` could be\n * used as the actual request body (the stream calls \"read()\").\n * We control the queue in the onRequestBody/End functions.\n */\n read: () => {\n // If the user attempts to read the request body,\n // flush the write buffer to trigger the callbacks.\n // This way, if the request stream ends in the write callback,\n // it will indeed end correctly.\n this.flushWriteBuffer()\n },\n })\n }\n\n const requestId = createRequestId()\n this.request = new Request(url, {\n method,\n headers,\n credentials: 'same-origin',\n // @ts-expect-error Undocumented Fetch property.\n duplex: canHaveBody ? 'half' : undefined,\n body: canHaveBody ? (Readable.toWeb(this.requestStream!) as any) : null,\n })\n\n Reflect.set(this.request, kRequestId, requestId)\n\n // Skip handling the request that's already being handled\n // by another (parent) interceptor. For example, XMLHttpRequest\n // is often implemented via ClientRequest in Node.js (e.g. JSDOM).\n // In that case, XHR interceptor will bubble down to the ClientRequest\n // interceptor. No need to try to handle that request again.\n /**\n * @fixme Stop relying on the \"X-Request-Id\" request header\n * to figure out if one interceptor has been invoked within another.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\n if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) {\n this.passthrough()\n return\n }\n\n this.onRequest({\n requestId,\n request: this.request,\n socket: this,\n })\n }\n\n private onRequestBody(chunk: Buffer): void {\n invariant(\n this.requestStream,\n 'Failed to write to a request stream: stream does not exist'\n )\n\n this.requestStream.push(chunk)\n }\n\n private onRequestEnd(): void {\n // Request end can be called for requests without body.\n if (this.requestStream) {\n this.requestStream.push(null)\n }\n }\n\n private onResponseStart: ResponseHeadersCompleteCallback = (\n versionMajor,\n versionMinor,\n rawHeaders,\n method,\n url,\n status,\n statusText\n ) => {\n const headers = FetchResponse.parseRawHeaders(rawHeaders)\n\n const response = new FetchResponse(\n /**\n * @note The Fetch API response instance exposed to the consumer\n * is created over the response stream of the HTTP parser. It is NOT\n * related to the Socket instance. This way, you can read response body\n * in response listener while the Socket instance delays the emission\n * of \"end\" and other events until those response listeners are finished.\n */\n FetchResponse.isResponseWithBody(status)\n ? (Readable.toWeb(\n (this.responseStream = new Readable({ read() {} }))\n ) as any)\n : null,\n {\n url,\n status,\n statusText,\n headers,\n }\n )\n\n invariant(\n this.request,\n 'Failed to handle a response: request does not exist'\n )\n\n /**\n * @fixme Stop relying on the \"X-Request-Id\" request header\n * to figure out if one interceptor has been invoked within another.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\n if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) {\n return\n }\n\n this.responseListenersPromise = this.onResponse({\n response,\n isMockedResponse: this.socketState === 'mock',\n requestId: Reflect.get(this.request, kRequestId),\n request: this.request,\n socket: this,\n })\n }\n\n private onResponseBody(chunk: Buffer) {\n invariant(\n this.responseStream,\n 'Failed to write to a response stream: stream does not exist'\n )\n\n this.responseStream.push(chunk)\n }\n\n private onResponseEnd(): void {\n // Response end can be called for responses without body.\n if (this.responseStream) {\n this.responseStream.push(null)\n }\n }\n}\n","import net from 'node:net'\nimport {\n normalizeSocketWriteArgs,\n type WriteArgs,\n type WriteCallback,\n} from './utils/normalizeSocketWriteArgs'\n\nexport interface MockSocketOptions {\n write: (\n chunk: Buffer | string,\n encoding: BufferEncoding | undefined,\n callback?: WriteCallback\n ) => void\n\n read: (chunk: Buffer, encoding: BufferEncoding | undefined) => void\n}\n\nexport class MockSocket extends net.Socket {\n public connecting: boolean\n\n constructor(protected readonly options: MockSocketOptions) {\n super()\n this.connecting = false\n this.connect()\n\n this._final = (callback) => {\n callback(null)\n }\n }\n\n public connect() {\n // The connection will remain pending until\n // the consumer decides to handle it.\n this.connecting = true\n return this\n }\n\n public write(...args: Array): boolean {\n const [chunk, encoding, callback] = normalizeSocketWriteArgs(\n args as WriteArgs\n )\n this.options.write(chunk, encoding, callback)\n return true\n }\n\n public end(...args: Array) {\n const [chunk, encoding, callback] = normalizeSocketWriteArgs(\n args as WriteArgs\n )\n this.options.write(chunk, encoding, callback)\n return super.end.apply(this, args as any)\n }\n\n public push(chunk: any, encoding?: BufferEncoding): boolean {\n this.options.read(chunk, encoding)\n return super.push(chunk, encoding)\n }\n}\n","export type WriteCallback = (error?: Error | null) => void\n\nexport type WriteArgs =\n | [chunk: unknown, callback?: WriteCallback]\n | [chunk: unknown, encoding: BufferEncoding, callback?: WriteCallback]\n\nexport type NormalizedSocketWriteArgs = [\n chunk: any,\n encoding?: BufferEncoding,\n callback?: WriteCallback,\n]\n\n/**\n * Normalizes the arguments provided to the `Writable.prototype.write()`\n * and `Writable.prototype.end()`.\n */\nexport function normalizeSocketWriteArgs(\n args: WriteArgs\n): NormalizedSocketWriteArgs {\n const normalized: NormalizedSocketWriteArgs = [args[0], undefined, undefined]\n\n if (typeof args[1] === 'string') {\n normalized[1] = args[1]\n } else if (typeof args[1] === 'function') {\n normalized[2] = args[1]\n }\n\n if (typeof args[2] === 'function') {\n normalized[2] = args[2]\n }\n\n return normalized\n}\n","export function baseUrlFromConnectionOptions(options: any): URL {\n if ('href' in options) {\n return new URL(options.href)\n }\n\n const protocol = options.port === 443 ? 'https:' : 'http:'\n const host = options.host\n\n const url = new URL(`${protocol}//${host}`)\n\n if (options.port) {\n url.port = options.port.toString()\n }\n\n if (options.path) {\n url.pathname = options.path\n }\n\n if (options.auth) {\n const [username, password] = options.auth.split(':')\n url.username = username\n url.password = password\n }\n\n return url\n}\n","type HeaderTuple = [string, string]\ntype RawHeaders = Array\ntype SetHeaderBehavior = 'set' | 'append'\n\nconst kRawHeaders = Symbol('kRawHeaders')\nconst kRestorePatches = Symbol('kRestorePatches')\n\nfunction recordRawHeader(\n headers: Headers,\n args: HeaderTuple,\n behavior: SetHeaderBehavior\n) {\n ensureRawHeadersSymbol(headers, [])\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n\n if (behavior === 'set') {\n // When recording a set header, ensure we remove any matching existing headers.\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n rawHeaders.push(args)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, this function does nothing.\n */\nfunction ensureRawHeadersSymbol(\n headers: Headers,\n rawHeaders: RawHeaders\n): void {\n if (Reflect.has(headers, kRawHeaders)) {\n return\n }\n\n defineRawHeadersSymbol(headers, rawHeaders)\n}\n\n/**\n * Define the raw headers symbol on the given `Headers` instance.\n * If the symbol already exists, it gets overridden.\n */\nfunction defineRawHeadersSymbol(headers: Headers, rawHeaders: RawHeaders) {\n Object.defineProperty(headers, kRawHeaders, {\n value: rawHeaders,\n enumerable: false,\n // Mark the symbol as configurable so its value can be overridden.\n // Overrides happen when merging raw headers from multiple sources.\n // E.g. new Request(new Request(url, { headers }), { headers })\n configurable: true,\n })\n}\n\n/**\n * Patch the global `Headers` class to store raw headers.\n * This is for compatibility with `IncomingMessage.prototype.rawHeaders`.\n *\n * @note Node.js has their own raw headers symbol but it\n * only records the first header name in case of multi-value headers.\n * Any other headers are normalized before comparing. This makes it\n * incompatible with the `rawHeaders` format.\n *\n * let h = new Headers()\n * h.append('X-Custom', 'one')\n * h.append('x-custom', 'two')\n * h[Symbol('headers map')] // Map { 'X-Custom' => 'one, two' }\n */\nexport function recordRawFetchHeaders() {\n // Prevent patching the Headers prototype multiple times.\n if (Reflect.get(Headers, kRestorePatches)) {\n return Reflect.get(Headers, kRestorePatches)\n }\n\n const {\n Headers: OriginalHeaders,\n Request: OriginalRequest,\n Response: OriginalResponse,\n } = globalThis\n const { set, append, delete: headersDeleteMethod } = Headers.prototype\n\n Object.defineProperty(Headers, kRestorePatches, {\n value: () => {\n Headers.prototype.set = set\n Headers.prototype.append = append\n Headers.prototype.delete = headersDeleteMethod\n globalThis.Headers = OriginalHeaders\n\n globalThis.Request = OriginalRequest\n globalThis.Response = OriginalResponse\n\n Reflect.deleteProperty(Headers, kRestorePatches)\n },\n enumerable: false,\n /**\n * @note Mark this property as configurable\n * so we can delete it using `Reflect.delete` during cleanup.\n */\n configurable: true,\n })\n\n Object.defineProperty(globalThis, 'Headers', {\n enumerable: true,\n writable: true,\n value: new Proxy(Headers, {\n construct(target, args, newTarget) {\n const headersInit = args[0] || []\n\n if (\n headersInit instanceof Headers &&\n Reflect.has(headersInit, kRawHeaders)\n ) {\n const headers = Reflect.construct(\n target,\n [Reflect.get(headersInit, kRawHeaders)],\n newTarget\n )\n ensureRawHeadersSymbol(headers, [\n /**\n * @note Spread the retrieved headers to clone them.\n * This prevents multiple Headers instances from pointing\n * at the same internal \"rawHeaders\" array.\n */\n ...Reflect.get(headersInit, kRawHeaders),\n ])\n return headers\n }\n\n const headers = Reflect.construct(target, args, newTarget)\n\n // Request/Response constructors will set the symbol\n // upon creating a new instance, using the raw developer\n // input as the raw headers. Skip the symbol altogether\n // in those cases because the input to Headers will be normalized.\n if (!Reflect.has(headers, kRawHeaders)) {\n const rawHeadersInit = Array.isArray(headersInit)\n ? headersInit\n : Object.entries(headersInit)\n ensureRawHeadersSymbol(headers, rawHeadersInit)\n }\n\n return headers\n },\n }),\n })\n\n Headers.prototype.set = new Proxy(Headers.prototype.set, {\n apply(target, thisArg, args: HeaderTuple) {\n recordRawHeader(thisArg, args, 'set')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.append = new Proxy(Headers.prototype.append, {\n apply(target, thisArg, args: HeaderTuple) {\n recordRawHeader(thisArg, args, 'append')\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Headers.prototype.delete = new Proxy(Headers.prototype.delete, {\n apply(target, thisArg, args: [string]) {\n const rawHeaders = Reflect.get(thisArg, kRawHeaders) as RawHeaders\n\n if (rawHeaders) {\n for (let index = rawHeaders.length - 1; index >= 0; index--) {\n if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) {\n rawHeaders.splice(index, 1)\n }\n }\n }\n\n return Reflect.apply(target, thisArg, args)\n },\n })\n\n Object.defineProperty(globalThis, 'Request', {\n enumerable: true,\n writable: true,\n value: new Proxy(Request, {\n construct(target, args, newTarget) {\n const request = Reflect.construct(target, args, newTarget)\n const inferredRawHeaders: RawHeaders = []\n\n // Infer raw headers from a `Request` instance used as init.\n if (typeof args[0] === 'object' && args[0].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[0].headers))\n }\n\n // Infer raw headers from the \"headers\" init argument.\n if (typeof args[1] === 'object' && args[1].headers != null) {\n inferredRawHeaders.push(...inferRawHeaders(args[1].headers))\n }\n\n if (inferredRawHeaders.length > 0) {\n ensureRawHeadersSymbol(request.headers, inferredRawHeaders)\n }\n\n return request\n },\n }),\n })\n\n Object.defineProperty(globalThis, 'Response', {\n enumerable: true,\n writable: true,\n value: new Proxy(Response, {\n construct(target, args, newTarget) {\n const response = Reflect.construct(target, args, newTarget)\n\n if (typeof args[1] === 'object' && args[1].headers != null) {\n ensureRawHeadersSymbol(\n response.headers,\n inferRawHeaders(args[1].headers)\n )\n }\n\n return response\n },\n }),\n })\n}\n\nexport function restoreHeadersPrototype() {\n if (!Reflect.get(Headers, kRestorePatches)) {\n return\n }\n\n Reflect.get(Headers, kRestorePatches)()\n}\n\nexport function getRawFetchHeaders(headers: Headers): RawHeaders {\n // If the raw headers recording failed for some reason,\n // use the normalized header entries instead.\n if (!Reflect.has(headers, kRawHeaders)) {\n return Array.from(headers.entries())\n }\n\n const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders\n return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries())\n}\n\n/**\n * Infers the raw headers from the given `HeadersInit` provided\n * to the Request/Response constructor.\n *\n * If the `init.headers` is a Headers instance, use it directly.\n * That means the headers were created standalone and already have\n * the raw headers stored.\n * If the `init.headers` is a HeadersInit, create a new Headers\n * instace out of it.\n */\nfunction inferRawHeaders(headers: HeadersInit): RawHeaders {\n if (headers instanceof Headers) {\n return Reflect.get(headers, kRawHeaders) || []\n }\n\n return Reflect.get(new Headers(headers), kRawHeaders)\n}\n","import net from 'node:net'\nimport http from 'node:http'\nimport https from 'node:https'\nimport {\n MockHttpSocket,\n type MockHttpSocketRequestCallback,\n type MockHttpSocketResponseCallback,\n} from './MockHttpSocket'\n\ndeclare module 'node:http' {\n interface Agent {\n createConnection(options: any, callback: any): net.Socket\n }\n}\n\ninterface MockAgentOptions {\n customAgent?: http.RequestOptions['agent']\n onRequest: MockHttpSocketRequestCallback\n onResponse: MockHttpSocketResponseCallback\n}\n\nexport class MockAgent extends http.Agent {\n private customAgent?: http.RequestOptions['agent']\n private onRequest: MockHttpSocketRequestCallback\n private onResponse: MockHttpSocketResponseCallback\n\n constructor(options: MockAgentOptions) {\n super()\n this.customAgent = options.customAgent\n this.onRequest = options.onRequest\n this.onResponse = options.onResponse\n }\n\n public createConnection(options: any, callback: any): net.Socket {\n const createConnection =\n (this.customAgent instanceof http.Agent &&\n this.customAgent.createConnection) ||\n super.createConnection\n\n const socket = new MockHttpSocket({\n connectionOptions: options,\n createConnection: createConnection.bind(\n this.customAgent || this,\n options,\n callback\n ),\n onRequest: this.onRequest.bind(this),\n onResponse: this.onResponse.bind(this),\n })\n\n return socket\n }\n}\n\nexport class MockHttpsAgent extends https.Agent {\n private customAgent?: https.RequestOptions['agent']\n private onRequest: MockHttpSocketRequestCallback\n private onResponse: MockHttpSocketResponseCallback\n\n constructor(options: MockAgentOptions) {\n super()\n this.customAgent = options.customAgent\n this.onRequest = options.onRequest\n this.onResponse = options.onResponse\n }\n\n public createConnection(options: any, callback: any): net.Socket {\n const createConnection =\n (this.customAgent instanceof https.Agent &&\n this.customAgent.createConnection) ||\n super.createConnection\n\n const socket = new MockHttpSocket({\n connectionOptions: options,\n createConnection: createConnection.bind(\n this.customAgent || this,\n options,\n callback\n ),\n onRequest: this.onRequest.bind(this),\n onResponse: this.onResponse.bind(this),\n })\n\n return socket\n }\n}\n","import { urlToHttpOptions } from 'node:url'\nimport {\n Agent as HttpAgent,\n globalAgent as httpGlobalAgent,\n IncomingMessage,\n} from 'node:http'\nimport {\n RequestOptions,\n Agent as HttpsAgent,\n globalAgent as httpsGlobalAgent,\n} from 'node:https'\nimport {\n /**\n * @note Use the Node.js URL instead of the global URL\n * because environments like JSDOM may override the global,\n * breaking the compatibility with Node.js.\n * @see https://github.com/node-fetch/node-fetch/issues/1376#issuecomment-966435555\n */\n URL,\n Url as LegacyURL,\n parse as parseUrl,\n} from 'node:url'\nimport { Logger } from '@open-draft/logger'\nimport {\n ResolvedRequestOptions,\n getUrlByRequestOptions,\n} from '../../../utils/getUrlByRequestOptions'\nimport { cloneObject } from '../../../utils/cloneObject'\nimport { isObject } from '../../../utils/isObject'\n\nconst logger = new Logger('http normalizeClientRequestArgs')\n\nexport type HttpRequestCallback = (response: IncomingMessage) => void\n\nexport type ClientRequestArgs =\n // Request without any arguments is also possible.\n | []\n | [string | URL | LegacyURL, HttpRequestCallback?]\n | [string | URL | LegacyURL, RequestOptions, HttpRequestCallback?]\n | [RequestOptions, HttpRequestCallback?]\n\nfunction resolveRequestOptions(\n args: ClientRequestArgs,\n url: URL\n): RequestOptions {\n // Calling `fetch` provides only URL to `ClientRequest`\n // without any `RequestOptions` or callback.\n if (typeof args[1] === 'undefined' || typeof args[1] === 'function') {\n logger.info('request options not provided, deriving from the url', url)\n return urlToHttpOptions(url)\n }\n\n if (args[1]) {\n logger.info('has custom RequestOptions!', args[1])\n const requestOptionsFromUrl = urlToHttpOptions(url)\n\n logger.info('derived RequestOptions from the URL:', requestOptionsFromUrl)\n\n /**\n * Clone the request options to lock their state\n * at the moment they are provided to `ClientRequest`.\n * @see https://github.com/mswjs/interceptors/issues/86\n */\n logger.info('cloning RequestOptions...')\n const clonedRequestOptions = cloneObject(args[1])\n logger.info('successfully cloned RequestOptions!', clonedRequestOptions)\n\n return {\n ...requestOptionsFromUrl,\n ...clonedRequestOptions,\n }\n }\n\n logger.info('using an empty object as request options')\n return {} as RequestOptions\n}\n\n/**\n * Overrides the given `URL` instance with the explicit properties provided\n * on the `RequestOptions` object. The options object takes precedence,\n * and will replace URL properties like \"host\", \"path\", and \"port\", if specified.\n */\nfunction overrideUrlByRequestOptions(url: URL, options: RequestOptions): URL {\n url.host = options.host || url.host\n url.hostname = options.hostname || url.hostname\n url.port = options.port ? options.port.toString() : url.port\n\n if (options.path) {\n const parsedOptionsPath = parseUrl(options.path, false)\n url.pathname = parsedOptionsPath.pathname || ''\n url.search = parsedOptionsPath.search || ''\n }\n\n return url\n}\n\nfunction resolveCallback(\n args: ClientRequestArgs\n): HttpRequestCallback | undefined {\n return typeof args[1] === 'function' ? args[1] : args[2]\n}\n\nexport type NormalizedClientRequestArgs = [\n url: URL,\n options: ResolvedRequestOptions,\n callback?: HttpRequestCallback\n]\n\n/**\n * Normalizes parameters given to a `http.request` call\n * so it always has a `URL` and `RequestOptions`.\n */\nexport function normalizeClientRequestArgs(\n defaultProtocol: string,\n args: ClientRequestArgs\n): NormalizedClientRequestArgs {\n let url: URL\n let options: ResolvedRequestOptions\n let callback: HttpRequestCallback | undefined\n\n logger.info('arguments', args)\n logger.info('using default protocol:', defaultProtocol)\n\n // Support \"http.request()\" calls without any arguments.\n // That call results in a \"GET http://localhost\" request.\n if (args.length === 0) {\n const url = new URL('http://localhost')\n const options = resolveRequestOptions(args, url)\n return [url, options]\n }\n\n // Convert a url string into a URL instance\n // and derive request options from it.\n if (typeof args[0] === 'string') {\n logger.info('first argument is a location string:', args[0])\n\n url = new URL(args[0])\n logger.info('created a url:', url)\n\n const requestOptionsFromUrl = urlToHttpOptions(url)\n logger.info('request options from url:', requestOptionsFromUrl)\n\n options = resolveRequestOptions(args, url)\n logger.info('resolved request options:', options)\n\n callback = resolveCallback(args)\n }\n // Handle a given URL instance as-is\n // and derive request options from it.\n else if (args[0] instanceof URL) {\n url = args[0]\n logger.info('first argument is a URL:', url)\n\n // Check if the second provided argument is RequestOptions.\n // If it is, check if \"options.path\" was set and rewrite it\n // on the input URL.\n // Do this before resolving options from the URL below\n // to prevent query string from being duplicated in the path.\n if (typeof args[1] !== 'undefined' && isObject(args[1])) {\n url = overrideUrlByRequestOptions(url, args[1])\n }\n\n options = resolveRequestOptions(args, url)\n logger.info('derived request options:', options)\n\n callback = resolveCallback(args)\n }\n // Handle a legacy URL instance and re-normalize from either a RequestOptions object\n // or a WHATWG URL.\n else if ('hash' in args[0] && !('method' in args[0])) {\n const [legacyUrl] = args\n logger.info('first argument is a legacy URL:', legacyUrl)\n\n if (legacyUrl.hostname === null) {\n /**\n * We are dealing with a relative url, so use the path as an \"option\" and\n * merge in any existing options, giving priority to exising options -- i.e. a path in any\n * existing options will take precedence over the one contained in the url. This is consistent\n * with the behaviour in ClientRequest.\n * @see https://github.com/nodejs/node/blob/d84f1312915fe45fe0febe888db692c74894c382/lib/_http_client.js#L122\n */\n logger.info('given legacy URL is relative (no hostname)')\n\n return isObject(args[1])\n ? normalizeClientRequestArgs(defaultProtocol, [\n { path: legacyUrl.path, ...args[1] },\n args[2],\n ])\n : normalizeClientRequestArgs(defaultProtocol, [\n { path: legacyUrl.path },\n args[1] as HttpRequestCallback,\n ])\n }\n\n logger.info('given legacy url is absolute')\n\n // We are dealing with an absolute URL, so convert to WHATWG and try again.\n const resolvedUrl = new URL(legacyUrl.href)\n\n return args[1] === undefined\n ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl])\n : typeof args[1] === 'function'\n ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl, args[1]])\n : normalizeClientRequestArgs(defaultProtocol, [\n resolvedUrl,\n args[1],\n args[2],\n ])\n }\n // Handle a given \"RequestOptions\" object as-is\n // and derive the URL instance from it.\n else if (isObject(args[0])) {\n options = { ...(args[0] as any) }\n logger.info('first argument is RequestOptions:', options)\n\n // When handling a \"RequestOptions\" object without an explicit \"protocol\",\n // infer the protocol from the request issuing module (http/https).\n options.protocol = options.protocol || defaultProtocol\n logger.info('normalized request options:', options)\n\n url = getUrlByRequestOptions(options)\n logger.info('created a URL from RequestOptions:', url.href)\n\n callback = resolveCallback(args)\n } else {\n throw new Error(\n `Failed to construct ClientRequest with these parameters: ${args}`\n )\n }\n\n options.protocol = options.protocol || url.protocol\n options.method = options.method || 'GET'\n\n /**\n * Infer a fallback agent from the URL protocol.\n * The interception is done on the \"ClientRequest\" level (\"NodeClientRequest\")\n * and it may miss the correct agent. Always align the agent\n * with the URL protocol, if not provided.\n *\n * @note Respect the \"agent: false\" value.\n */\n if (typeof options.agent === 'undefined') {\n const agent =\n options.protocol === 'https:'\n ? new HttpsAgent({\n rejectUnauthorized: options.rejectUnauthorized,\n })\n : new HttpAgent()\n\n options.agent = agent\n logger.info('resolved fallback agent:', agent)\n }\n\n /**\n * Ensure that the default Agent is always set.\n * This prevents the protocol mismatch for requests with { agent: false },\n * where the global Agent is inferred.\n * @see https://github.com/mswjs/msw/issues/1150\n * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L130\n * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L157-L159\n */\n if (!options._defaultAgent) {\n logger.info(\n 'has no default agent, setting the default agent for \"%s\"',\n options.protocol\n )\n\n options._defaultAgent =\n options.protocol === 'https:' ? httpsGlobalAgent : httpGlobalAgent\n }\n\n logger.info('successfully resolved url:', url.href)\n logger.info('successfully resolved options:', options)\n logger.info('successfully resolved callback:', callback)\n\n /**\n * @note If the user-provided URL is not a valid URL in Node.js,\n * (e.g. the one provided by the JSDOM polyfills), case it to\n * string. Otherwise, this throws on Node.js incompatibility\n * (`ERR_INVALID_ARG_TYPE` on the connection listener)\n * @see https://github.com/node-fetch/node-fetch/issues/1376#issuecomment-966435555\n */\n if (!(url instanceof URL)) {\n url = (url as any).toString()\n }\n\n return [url, options, callback]\n}\n","import { Agent } from 'http'\nimport { RequestOptions, Agent as HttpsAgent } from 'https'\nimport { Logger } from '@open-draft/logger'\n\nconst logger = new Logger('utils getUrlByRequestOptions')\n\n// Request instance constructed by the \"request\" library\n// has a \"self\" property that has a \"uri\" field. This is\n// reproducible by performing a \"XMLHttpRequest\" request in JSDOM.\nexport interface RequestSelf {\n uri?: URL\n}\n\nexport type ResolvedRequestOptions = RequestOptions & RequestSelf\n\nexport const DEFAULT_PATH = '/'\nconst DEFAULT_PROTOCOL = 'http:'\nconst DEFAULT_HOSTNAME = 'localhost'\nconst SSL_PORT = 443\n\nfunction getAgent(\n options: ResolvedRequestOptions\n): Agent | HttpsAgent | undefined {\n return options.agent instanceof Agent ? options.agent : undefined\n}\n\nfunction getProtocolByRequestOptions(options: ResolvedRequestOptions): string {\n if (options.protocol) {\n return options.protocol\n }\n\n const agent = getAgent(options)\n const agentProtocol = (agent as RequestOptions)?.protocol\n\n if (agentProtocol) {\n return agentProtocol\n }\n\n const port = getPortByRequestOptions(options)\n const isSecureRequest = options.cert || port === SSL_PORT\n\n return isSecureRequest ? 'https:' : options.uri?.protocol || DEFAULT_PROTOCOL\n}\n\nfunction getPortByRequestOptions(\n options: ResolvedRequestOptions\n): number | undefined {\n // Use the explicitly provided port.\n if (options.port) {\n return Number(options.port)\n }\n\n // Otherwise, try to resolve port from the agent.\n const agent = getAgent(options)\n\n if ((agent as HttpsAgent)?.options.port) {\n return Number((agent as HttpsAgent).options.port)\n }\n\n if ((agent as RequestOptions)?.defaultPort) {\n return Number((agent as RequestOptions).defaultPort)\n }\n\n // Lastly, return undefined indicating that the port\n // must inferred from the protocol. Do not infer it here.\n return undefined\n}\n\ninterface RequestAuth {\n username: string\n password: string\n}\n\nfunction getAuthByRequestOptions(\n options: ResolvedRequestOptions\n): RequestAuth | undefined {\n if (options.auth) {\n const [username, password] = options.auth.split(':')\n return { username, password }\n }\n}\n\n/**\n * Returns true if host looks like an IPv6 address without surrounding brackets\n * It assumes any host containing `:` is definitely not IPv4 and probably IPv6,\n * but note that this could include invalid IPv6 addresses as well.\n */\nfunction isRawIPv6Address(host: string): boolean {\n return host.includes(':') && !host.startsWith('[') && !host.endsWith(']')\n}\n\nfunction getHostname(options: ResolvedRequestOptions): string | undefined {\n let host = options.hostname || options.host\n\n if (host) {\n if (isRawIPv6Address(host)) {\n host = `[${host}]`\n }\n\n // Check the presence of the port, and if it's present,\n // remove it from the host, returning a hostname.\n return new URL(`http://${host}`).hostname\n }\n\n return DEFAULT_HOSTNAME\n}\n\n/**\n * Creates a `URL` instance from a given `RequestOptions` object.\n */\nexport function getUrlByRequestOptions(options: ResolvedRequestOptions): URL {\n logger.info('request options', options)\n\n if (options.uri) {\n logger.info(\n 'constructing url from explicitly provided \"options.uri\": %s',\n options.uri\n )\n return new URL(options.uri.href)\n }\n\n logger.info('figuring out url from request options...')\n\n const protocol = getProtocolByRequestOptions(options)\n logger.info('protocol', protocol)\n\n const port = getPortByRequestOptions(options)\n logger.info('port', port)\n\n const hostname = getHostname(options)\n logger.info('hostname', hostname)\n\n const path = options.path || DEFAULT_PATH\n logger.info('path', path)\n\n const credentials = getAuthByRequestOptions(options)\n logger.info('credentials', credentials)\n\n const authString = credentials\n ? `${credentials.username}:${credentials.password}@`\n : ''\n logger.info('auth string:', authString)\n\n const portString = typeof port !== 'undefined' ? `:${port}` : ''\n const url = new URL(`${protocol}//${hostname}${portString}${path}`)\n url.username = credentials?.username || ''\n url.password = credentials?.password || ''\n\n logger.info('created url:', url)\n\n return url\n}\n","import { Logger } from '@open-draft/logger'\n\nconst logger = new Logger('cloneObject')\n\nfunction isPlainObject(obj?: Record): boolean {\n logger.info('is plain object?', obj)\n\n if (obj == null || !obj.constructor?.name) {\n logger.info('given object is undefined, not a plain object...')\n return false\n }\n\n logger.info('checking the object constructor:', obj.constructor.name)\n return obj.constructor.name === 'Object'\n}\n\nexport function cloneObject>(\n obj: ObjectType\n): ObjectType {\n logger.info('cloning object:', obj)\n\n const enumerableProperties = Object.entries(obj).reduce>(\n (acc, [key, value]) => {\n logger.info('analyzing key-value pair:', key, value)\n\n // Recursively clone only plain objects, omitting class instances.\n acc[key] = isPlainObject(value) ? cloneObject(value) : value\n return acc\n },\n {}\n )\n\n return isPlainObject(obj)\n ? enumerableProperties\n : Object.assign(Object.getPrototypeOf(obj), enumerableProperties)\n}\n","/**\n * Determines if a given value is an instance of object.\n */\nexport function isObject(value: any, loose = false): value is T {\n return loose\n ? Object.prototype.toString.call(value).startsWith('[object ')\n : Object.prototype.toString.call(value) === '[object Object]'\n}\n"],"mappings":"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","names":["http","https","net","headers","net","URL","Logger","Logger","logger","logger","Logger","url","URL","options","http","https"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-TX5GBTFY.mjs b/node_modules/@mswjs/interceptors/lib/node/chunk-TX5GBTFY.mjs new file mode 100644 index 0000000000..f42b2faa86 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-TX5GBTFY.mjs @@ -0,0 +1,25 @@ +// src/utils/hasConfigurableGlobal.ts +function hasConfigurableGlobal(propertyName) { + const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName); + if (typeof descriptor === "undefined") { + return false; + } + if (typeof descriptor.get === "function" && typeof descriptor.get() === "undefined") { + return false; + } + if (typeof descriptor.get === "undefined" && descriptor.value == null) { + return false; + } + if (typeof descriptor.set === "undefined" && !descriptor.configurable) { + console.error( + `[MSW] Failed to apply interceptor: the global \`${propertyName}\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.` + ); + return false; + } + return true; +} + +export { + hasConfigurableGlobal +}; +//# sourceMappingURL=chunk-TX5GBTFY.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-TX5GBTFY.mjs.map b/node_modules/@mswjs/interceptors/lib/node/chunk-TX5GBTFY.mjs.map new file mode 100644 index 0000000000..c5a9cb80f9 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-TX5GBTFY.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/hasConfigurableGlobal.ts"],"sourcesContent":["/**\n * Returns a boolean indicating whether the given global property\n * is defined and is configurable.\n */\nexport function hasConfigurableGlobal(propertyName: string): boolean {\n const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName)\n\n // The property is not set at all.\n if (typeof descriptor === 'undefined') {\n return false\n }\n\n // The property is set to a getter that returns undefined.\n if (\n typeof descriptor.get === 'function' &&\n typeof descriptor.get() === 'undefined'\n ) {\n return false\n }\n\n // The property is set to a value equal to undefined.\n if (typeof descriptor.get === 'undefined' && descriptor.value == null) {\n return false\n }\n\n if (typeof descriptor.set === 'undefined' && !descriptor.configurable) {\n console.error(\n `[MSW] Failed to apply interceptor: the global \\`${propertyName}\\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.`\n )\n return false\n }\n\n return true\n}\n"],"mappings":";AAIO,SAAS,sBAAsB,cAA+B;AACnE,QAAM,aAAa,OAAO,yBAAyB,YAAY,YAAY;AAG3E,MAAI,OAAO,eAAe,aAAa;AACrC,WAAO;AAAA,EACT;AAGA,MACE,OAAO,WAAW,QAAQ,cAC1B,OAAO,WAAW,IAAI,MAAM,aAC5B;AACA,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,WAAW,QAAQ,eAAe,WAAW,SAAS,MAAM;AACrE,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,QAAQ,eAAe,CAAC,WAAW,cAAc;AACrE,YAAQ;AAAA,MACN,mDAAmD;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-WZTE4PCO.js b/node_modules/@mswjs/interceptors/lib/node/chunk-WZTE4PCO.js new file mode 100644 index 0000000000..9230ad0c32 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-WZTE4PCO.js @@ -0,0 +1,245 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/Interceptor.ts +var _logger = require('@open-draft/logger'); +var _stricteventemitter = require('strict-event-emitter'); +var INTERNAL_REQUEST_ID_HEADER_NAME = "x-interceptors-internal-request-id"; +function getGlobalSymbol(symbol) { + return ( + // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587 + globalThis[symbol] || void 0 + ); +} +function setGlobalSymbol(symbol, value) { + globalThis[symbol] = value; +} +function deleteGlobalSymbol(symbol) { + delete globalThis[symbol]; +} +var InterceptorReadyState = /* @__PURE__ */ ((InterceptorReadyState2) => { + InterceptorReadyState2["INACTIVE"] = "INACTIVE"; + InterceptorReadyState2["APPLYING"] = "APPLYING"; + InterceptorReadyState2["APPLIED"] = "APPLIED"; + InterceptorReadyState2["DISPOSING"] = "DISPOSING"; + InterceptorReadyState2["DISPOSED"] = "DISPOSED"; + return InterceptorReadyState2; +})(InterceptorReadyState || {}); +var Interceptor = class { + constructor(symbol) { + this.symbol = symbol; + this.readyState = "INACTIVE" /* INACTIVE */; + this.emitter = new (0, _stricteventemitter.Emitter)(); + this.subscriptions = []; + this.logger = new (0, _logger.Logger)(symbol.description); + this.emitter.setMaxListeners(0); + this.logger.info("constructing the interceptor..."); + } + /** + * Determine if this interceptor can be applied + * in the current environment. + */ + checkEnvironment() { + return true; + } + /** + * Apply this interceptor to the current process. + * Returns an already running interceptor instance if it's present. + */ + apply() { + const logger = this.logger.extend("apply"); + logger.info("applying the interceptor..."); + if (this.readyState === "APPLIED" /* APPLIED */) { + logger.info("intercepted already applied!"); + return; + } + const shouldApply = this.checkEnvironment(); + if (!shouldApply) { + logger.info("the interceptor cannot be applied in this environment!"); + return; + } + this.readyState = "APPLYING" /* APPLYING */; + const runningInstance = this.getInstance(); + if (runningInstance) { + logger.info("found a running instance, reusing..."); + this.on = (event, listener) => { + logger.info('proxying the "%s" listener', event); + runningInstance.emitter.addListener(event, listener); + this.subscriptions.push(() => { + runningInstance.emitter.removeListener(event, listener); + logger.info('removed proxied "%s" listener!', event); + }); + return this; + }; + this.readyState = "APPLIED" /* APPLIED */; + return; + } + logger.info("no running instance found, setting up a new instance..."); + this.setup(); + this.setInstance(); + this.readyState = "APPLIED" /* APPLIED */; + } + /** + * Setup the module augments and stubs necessary for this interceptor. + * This method is not run if there's a running interceptor instance + * to prevent instantiating an interceptor multiple times. + */ + setup() { + } + /** + * Listen to the interceptor's public events. + */ + on(event, listener) { + const logger = this.logger.extend("on"); + if (this.readyState === "DISPOSING" /* DISPOSING */ || this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot listen to events, already disposed!"); + return this; + } + logger.info('adding "%s" event listener:', event, listener); + this.emitter.on(event, listener); + return this; + } + once(event, listener) { + this.emitter.once(event, listener); + return this; + } + off(event, listener) { + this.emitter.off(event, listener); + return this; + } + removeAllListeners(event) { + this.emitter.removeAllListeners(event); + return this; + } + /** + * Disposes of any side-effects this interceptor has introduced. + */ + dispose() { + const logger = this.logger.extend("dispose"); + if (this.readyState === "DISPOSED" /* DISPOSED */) { + logger.info("cannot dispose, already disposed!"); + return; + } + logger.info("disposing the interceptor..."); + this.readyState = "DISPOSING" /* DISPOSING */; + if (!this.getInstance()) { + logger.info("no interceptors running, skipping dispose..."); + return; + } + this.clearInstance(); + logger.info("global symbol deleted:", getGlobalSymbol(this.symbol)); + if (this.subscriptions.length > 0) { + logger.info("disposing of %d subscriptions...", this.subscriptions.length); + for (const dispose of this.subscriptions) { + dispose(); + } + this.subscriptions = []; + logger.info("disposed of all subscriptions!", this.subscriptions.length); + } + this.emitter.removeAllListeners(); + logger.info("destroyed the listener!"); + this.readyState = "DISPOSED" /* DISPOSED */; + } + getInstance() { + var _a; + const instance = getGlobalSymbol(this.symbol); + this.logger.info("retrieved global instance:", (_a = instance == null ? void 0 : instance.constructor) == null ? void 0 : _a.name); + return instance; + } + setInstance() { + setGlobalSymbol(this.symbol, this); + this.logger.info("set global instance!", this.symbol.description); + } + clearInstance() { + deleteGlobalSymbol(this.symbol); + this.logger.info("cleared global instance!", this.symbol.description); + } +}; + +// src/createRequestId.ts +function createRequestId() { + return Math.random().toString(16).slice(2); +} + +// src/utils/fetchUtils.ts +var _FetchResponse = class extends Response { + static isConfigurableStatusCode(status) { + return status >= 200 && status <= 599; + } + static isRedirectResponse(status) { + return _FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status); + } + /** + * Returns a boolean indicating whether the given response status + * code represents a response that can have a body. + */ + static isResponseWithBody(status) { + return !_FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status); + } + static setUrl(url, response) { + if (!url) { + return; + } + if (response.url != "") { + return; + } + Object.defineProperty(response, "url", { + value: url, + enumerable: true, + configurable: true, + writable: false + }); + } + /** + * Parses the given raw HTTP headers into a Fetch API `Headers` instance. + */ + static parseRawHeaders(rawHeaders) { + const headers = new Headers(); + for (let line = 0; line < rawHeaders.length; line += 2) { + headers.append(rawHeaders[line], rawHeaders[line + 1]); + } + return headers; + } + constructor(body, init = {}) { + var _a; + const status = (_a = init.status) != null ? _a : 200; + const safeStatus = _FetchResponse.isConfigurableStatusCode(status) ? status : 200; + const finalBody = _FetchResponse.isResponseWithBody(status) ? body : null; + super(finalBody, { + ...init, + status: safeStatus + }); + if (status !== safeStatus) { + const stateSymbol = Object.getOwnPropertySymbols(this).find( + (symbol) => symbol.description === "state" + ); + if (stateSymbol) { + const state = Reflect.get(this, stateSymbol); + Reflect.set(state, "status", status); + } else { + Object.defineProperty(this, "status", { + value: status, + enumerable: true, + configurable: true, + writable: false + }); + } + } + _FetchResponse.setUrl(init.url, this); + } +}; +var FetchResponse = _FetchResponse; +/** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ +FetchResponse.STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]; +FetchResponse.STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]; + + + + + + + + + +exports.INTERNAL_REQUEST_ID_HEADER_NAME = INTERNAL_REQUEST_ID_HEADER_NAME; exports.getGlobalSymbol = getGlobalSymbol; exports.deleteGlobalSymbol = deleteGlobalSymbol; exports.InterceptorReadyState = InterceptorReadyState; exports.Interceptor = Interceptor; exports.createRequestId = createRequestId; exports.FetchResponse = FetchResponse; +//# sourceMappingURL=chunk-WZTE4PCO.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-WZTE4PCO.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-WZTE4PCO.js.map new file mode 100644 index 0000000000..f10d0d5c84 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-WZTE4PCO.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/Interceptor.ts","../../src/createRequestId.ts","../../src/utils/fetchUtils.ts"],"names":["InterceptorReadyState"],"mappings":"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","sourcesContent":["import { Logger } from '@open-draft/logger'\nimport { Emitter, Listener } from 'strict-event-emitter'\n\nexport type InterceptorEventMap = Record\nexport type InterceptorSubscription = () => void\n\n/**\n * Request header name to detect when a single request\n * is being handled by nested interceptors (XHR -> ClientRequest).\n * Obscure by design to prevent collisions with user-defined headers.\n * Ideally, come up with the Interceptor-level mechanism for this.\n * @see https://github.com/mswjs/interceptors/issues/378\n */\nexport const INTERNAL_REQUEST_ID_HEADER_NAME =\n 'x-interceptors-internal-request-id'\n\nexport function getGlobalSymbol(symbol: Symbol): V | undefined {\n return (\n // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587\n globalThis[symbol] || undefined\n )\n}\n\nfunction setGlobalSymbol(symbol: Symbol, value: any): void {\n // @ts-ignore\n globalThis[symbol] = value\n}\n\nexport function deleteGlobalSymbol(symbol: Symbol): void {\n // @ts-ignore\n delete globalThis[symbol]\n}\n\nexport enum InterceptorReadyState {\n INACTIVE = 'INACTIVE',\n APPLYING = 'APPLYING',\n APPLIED = 'APPLIED',\n DISPOSING = 'DISPOSING',\n DISPOSED = 'DISPOSED',\n}\n\nexport type ExtractEventNames> =\n Events extends Record ? EventName : never\n\nexport class Interceptor {\n protected emitter: Emitter\n protected subscriptions: Array\n protected logger: Logger\n\n public readyState: InterceptorReadyState\n\n constructor(private readonly symbol: symbol) {\n this.readyState = InterceptorReadyState.INACTIVE\n\n this.emitter = new Emitter()\n this.subscriptions = []\n this.logger = new Logger(symbol.description!)\n\n // Do not limit the maximum number of listeners\n // so not to limit the maximum amount of parallel events emitted.\n this.emitter.setMaxListeners(0)\n\n this.logger.info('constructing the interceptor...')\n }\n\n /**\n * Determine if this interceptor can be applied\n * in the current environment.\n */\n protected checkEnvironment(): boolean {\n return true\n }\n\n /**\n * Apply this interceptor to the current process.\n * Returns an already running interceptor instance if it's present.\n */\n public apply(): void {\n const logger = this.logger.extend('apply')\n logger.info('applying the interceptor...')\n\n if (this.readyState === InterceptorReadyState.APPLIED) {\n logger.info('intercepted already applied!')\n return\n }\n\n const shouldApply = this.checkEnvironment()\n\n if (!shouldApply) {\n logger.info('the interceptor cannot be applied in this environment!')\n return\n }\n\n this.readyState = InterceptorReadyState.APPLYING\n\n // Whenever applying a new interceptor, check if it hasn't been applied already.\n // This enables to apply the same interceptor multiple times, for example from a different\n // interceptor, only proxying events but keeping the stubs in a single place.\n const runningInstance = this.getInstance()\n\n if (runningInstance) {\n logger.info('found a running instance, reusing...')\n\n // Proxy any listeners you set on this instance to the running instance.\n this.on = (event, listener) => {\n logger.info('proxying the \"%s\" listener', event)\n\n // Add listeners to the running instance so they appear\n // at the top of the event listeners list and are executed first.\n runningInstance.emitter.addListener(event, listener)\n\n // Ensure that once this interceptor instance is disposed,\n // it removes all listeners it has appended to the running interceptor instance.\n this.subscriptions.push(() => {\n runningInstance.emitter.removeListener(event, listener)\n logger.info('removed proxied \"%s\" listener!', event)\n })\n\n return this\n }\n\n this.readyState = InterceptorReadyState.APPLIED\n\n return\n }\n\n logger.info('no running instance found, setting up a new instance...')\n\n // Setup the interceptor.\n this.setup()\n\n // Store the newly applied interceptor instance globally.\n this.setInstance()\n\n this.readyState = InterceptorReadyState.APPLIED\n }\n\n /**\n * Setup the module augments and stubs necessary for this interceptor.\n * This method is not run if there's a running interceptor instance\n * to prevent instantiating an interceptor multiple times.\n */\n protected setup(): void {}\n\n /**\n * Listen to the interceptor's public events.\n */\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n const logger = this.logger.extend('on')\n\n if (\n this.readyState === InterceptorReadyState.DISPOSING ||\n this.readyState === InterceptorReadyState.DISPOSED\n ) {\n logger.info('cannot listen to events, already disposed!')\n return this\n }\n\n logger.info('adding \"%s\" event listener:', event, listener)\n\n this.emitter.on(event, listener)\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.once(event, listener)\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n this.emitter.off(event, listener)\n return this\n }\n\n public removeAllListeners>(\n event?: EventName\n ): this {\n this.emitter.removeAllListeners(event)\n return this\n }\n\n /**\n * Disposes of any side-effects this interceptor has introduced.\n */\n public dispose(): void {\n const logger = this.logger.extend('dispose')\n\n if (this.readyState === InterceptorReadyState.DISPOSED) {\n logger.info('cannot dispose, already disposed!')\n return\n }\n\n logger.info('disposing the interceptor...')\n this.readyState = InterceptorReadyState.DISPOSING\n\n if (!this.getInstance()) {\n logger.info('no interceptors running, skipping dispose...')\n return\n }\n\n // Delete the global symbol as soon as possible,\n // indicating that the interceptor is no longer running.\n this.clearInstance()\n\n logger.info('global symbol deleted:', getGlobalSymbol(this.symbol))\n\n if (this.subscriptions.length > 0) {\n logger.info('disposing of %d subscriptions...', this.subscriptions.length)\n\n for (const dispose of this.subscriptions) {\n dispose()\n }\n\n this.subscriptions = []\n\n logger.info('disposed of all subscriptions!', this.subscriptions.length)\n }\n\n this.emitter.removeAllListeners()\n logger.info('destroyed the listener!')\n\n this.readyState = InterceptorReadyState.DISPOSED\n }\n\n private getInstance(): this | undefined {\n const instance = getGlobalSymbol(this.symbol)\n this.logger.info('retrieved global instance:', instance?.constructor?.name)\n return instance\n }\n\n private setInstance(): void {\n setGlobalSymbol(this.symbol, this)\n this.logger.info('set global instance!', this.symbol.description)\n }\n\n private clearInstance(): void {\n deleteGlobalSymbol(this.symbol)\n this.logger.info('cleared global instance!', this.symbol.description)\n }\n}\n","/**\n * Generate a random ID string to represent a request.\n * @example\n * createRequestId()\n * // \"f774b6c9c600f\"\n */\nexport function createRequestId(): string {\n return Math.random().toString(16).slice(2)\n}\n","export interface FetchResponseInit extends ResponseInit {\n url?: string\n}\n\nexport class FetchResponse extends Response {\n /**\n * Response status codes for responses that cannot have body.\n * @see https://fetch.spec.whatwg.org/#statuses\n */\n static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304]\n\n static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308]\n\n static isConfigurableStatusCode(status: number): boolean {\n return status >= 200 && status <= 599\n }\n\n static isRedirectResponse(status: number): boolean {\n return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status)\n }\n\n /**\n * Returns a boolean indicating whether the given response status\n * code represents a response that can have a body.\n */\n static isResponseWithBody(status: number): boolean {\n return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status)\n }\n\n static setUrl(url: string | undefined, response: Response): void {\n if (!url) {\n return\n }\n\n if (response.url != '') {\n return\n }\n\n Object.defineProperty(response, 'url', {\n value: url,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n\n /**\n * Parses the given raw HTTP headers into a Fetch API `Headers` instance.\n */\n static parseRawHeaders(rawHeaders: Array): Headers {\n const headers = new Headers()\n for (let line = 0; line < rawHeaders.length; line += 2) {\n headers.append(rawHeaders[line], rawHeaders[line + 1])\n }\n return headers\n }\n\n constructor(body?: BodyInit | null, init: FetchResponseInit = {}) {\n const status = init.status ?? 200\n const safeStatus = FetchResponse.isConfigurableStatusCode(status)\n ? status\n : 200\n const finalBody = FetchResponse.isResponseWithBody(status) ? body : null\n\n super(finalBody, {\n ...init,\n status: safeStatus,\n })\n\n if (status !== safeStatus) {\n /**\n * @note Undici keeps an internal \"Symbol(state)\" that holds\n * the actual value of response status. Update that in Node.js.\n */\n const stateSymbol = Object.getOwnPropertySymbols(this).find(\n (symbol) => symbol.description === 'state'\n )\n if (stateSymbol) {\n const state = Reflect.get(this, stateSymbol) as object\n Reflect.set(state, 'status', status)\n } else {\n Object.defineProperty(this, 'status', {\n value: status,\n enumerable: true,\n configurable: true,\n writable: false,\n })\n }\n }\n\n FetchResponse.setUrl(init.url, this)\n }\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-YBN5MFAP.js b/node_modules/@mswjs/interceptors/lib/node/chunk-YBN5MFAP.js new file mode 100644 index 0000000000..b44060531b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-YBN5MFAP.js @@ -0,0 +1,51 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkWZTE4PCOjs = require('./chunk-WZTE4PCO.js'); + +// src/BatchInterceptor.ts +var BatchInterceptor = class extends _chunkWZTE4PCOjs.Interceptor { + constructor(options) { + BatchInterceptor.symbol = Symbol(options.name); + super(BatchInterceptor.symbol); + this.interceptors = options.interceptors; + } + setup() { + const logger = this.logger.extend("setup"); + logger.info("applying all %d interceptors...", this.interceptors.length); + for (const interceptor of this.interceptors) { + logger.info('applying "%s" interceptor...', interceptor.constructor.name); + interceptor.apply(); + logger.info("adding interceptor dispose subscription"); + this.subscriptions.push(() => interceptor.dispose()); + } + } + on(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.on(event, listener); + } + return this; + } + once(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.once(event, listener); + } + return this; + } + off(event, listener) { + for (const interceptor of this.interceptors) { + interceptor.off(event, listener); + } + return this; + } + removeAllListeners(event) { + for (const interceptors of this.interceptors) { + interceptors.removeAllListeners(event); + } + return this; + } +}; + + + +exports.BatchInterceptor = BatchInterceptor; +//# sourceMappingURL=chunk-YBN5MFAP.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/chunk-YBN5MFAP.js.map b/node_modules/@mswjs/interceptors/lib/node/chunk-YBN5MFAP.js.map new file mode 100644 index 0000000000..968f3b814b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/chunk-YBN5MFAP.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/BatchInterceptor.ts"],"names":[],"mappings":";;;;;AAsBO,IAAM,mBAAN,cAGG,YAAoB;AAAA,EAK5B,YAAY,SAAmD;AAC7D,qBAAiB,SAAS,OAAO,QAAQ,IAAI;AAC7C,UAAM,iBAAiB,MAAM;AAC7B,SAAK,eAAe,QAAQ;AAAA,EAC9B;AAAA,EAEU,QAAQ;AAChB,UAAM,SAAS,KAAK,OAAO,OAAO,OAAO;AAEzC,WAAO,KAAK,mCAAmC,KAAK,aAAa,MAAM;AAEvE,eAAW,eAAe,KAAK,cAAc;AAC3C,aAAO,KAAK,gCAAgC,YAAY,YAAY,IAAI;AACxE,kBAAY,MAAM;AAElB,aAAO,KAAK,yCAAyC;AACrD,WAAK,cAAc,KAAK,MAAM,YAAY,QAAQ,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,GACL,OACA,UACM;AAGN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,GAAG,OAAO,QAAQ;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,KACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,KAAK,OAAO,QAAQ;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,OACA,UACM;AACN,eAAW,eAAe,KAAK,cAAc;AAC3C,kBAAY,IAAI,OAAO,QAAQ;AAAA,IACjC;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,mBACL,OACM;AACN,eAAW,gBAAgB,KAAK,cAAc;AAC5C,mBAAa,mBAAmB,KAAK;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AACF","sourcesContent":["import { EventMap, Listener } from 'strict-event-emitter'\nimport { Interceptor, ExtractEventNames } from './Interceptor'\n\nexport interface BatchInterceptorOptions<\n InterceptorList extends ReadonlyArray>\n> {\n name: string\n interceptors: InterceptorList\n}\n\nexport type ExtractEventMapType<\n InterceptorList extends ReadonlyArray>\n> = InterceptorList extends ReadonlyArray\n ? InterceptorType extends Interceptor\n ? EventMap\n : never\n : never\n\n/**\n * A batch interceptor that exposes a single interface\n * to apply and operate with multiple interceptors at once.\n */\nexport class BatchInterceptor<\n InterceptorList extends ReadonlyArray>,\n Events extends EventMap = ExtractEventMapType\n> extends Interceptor {\n static symbol: symbol\n\n private interceptors: InterceptorList\n\n constructor(options: BatchInterceptorOptions) {\n BatchInterceptor.symbol = Symbol(options.name)\n super(BatchInterceptor.symbol)\n this.interceptors = options.interceptors\n }\n\n protected setup() {\n const logger = this.logger.extend('setup')\n\n logger.info('applying all %d interceptors...', this.interceptors.length)\n\n for (const interceptor of this.interceptors) {\n logger.info('applying \"%s\" interceptor...', interceptor.constructor.name)\n interceptor.apply()\n\n logger.info('adding interceptor dispose subscription')\n this.subscriptions.push(() => interceptor.dispose())\n }\n }\n\n public on>(\n event: EventName,\n listener: Listener\n ): this {\n // Instead of adding a listener to the batch interceptor,\n // propagate the listener to each of the individual interceptors.\n for (const interceptor of this.interceptors) {\n interceptor.on(event, listener)\n }\n\n return this\n }\n\n public once>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.once(event, listener)\n }\n\n return this\n }\n\n public off>(\n event: EventName,\n listener: Listener\n ): this {\n for (const interceptor of this.interceptors) {\n interceptor.off(event, listener)\n }\n\n return this\n }\n\n public removeAllListeners>(\n event?: EventName | undefined\n ): this {\n for (const interceptors of this.interceptors) {\n interceptors.removeAllListeners(event)\n }\n\n return this\n }\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/index.d.ts b/node_modules/@mswjs/interceptors/lib/node/index.d.ts new file mode 100644 index 0000000000..6a78c7d9c2 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/index.d.ts @@ -0,0 +1,48 @@ +export { E as ExtractEventNames, H as HttpRequestEventMap, d as INTERNAL_REQUEST_ID_HEADER_NAME, I as IS_PATCHED_MODULE, h as Interceptor, b as InterceptorEventMap, f as InterceptorReadyState, c as InterceptorSubscription, R as RequestController, a as RequestCredentials, e as deleteGlobalSymbol, g as getGlobalSymbol } from './Interceptor-436630be.js'; +export { a as BatchInterceptor, B as BatchInterceptorOptions, E as ExtractEventMapType } from './BatchInterceptor-67bf41ba.js'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; +import 'strict-event-emitter'; + +/** + * Generate a random ID string to represent a request. + * @example + * createRequestId() + * // "f774b6c9c600f" + */ +declare function createRequestId(): string; + +/** + * Removes query parameters and hashes from a given URL. + */ +declare function getCleanUrl(url: URL, isAbsolute?: boolean): string; + +declare function encodeBuffer(text: string): Uint8Array; +declare function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string; + +interface FetchResponseInit extends ResponseInit { + url?: string; +} +declare class FetchResponse extends Response { + /** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ + static readonly STATUS_CODES_WITHOUT_BODY: number[]; + static readonly STATUS_CODES_WITH_REDIRECT: number[]; + static isConfigurableStatusCode(status: number): boolean; + static isRedirectResponse(status: number): boolean; + /** + * Returns a boolean indicating whether the given response status + * code represents a response that can have a body. + */ + static isResponseWithBody(status: number): boolean; + static setUrl(url: string | undefined, response: Response): void; + /** + * Parses the given raw HTTP headers into a Fetch API `Headers` instance. + */ + static parseRawHeaders(rawHeaders: Array): Headers; + constructor(body?: BodyInit | null, init?: FetchResponseInit); +} + +export { FetchResponse, createRequestId, decodeBuffer, encodeBuffer, getCleanUrl }; diff --git a/node_modules/@mswjs/interceptors/lib/node/index.js b/node_modules/@mswjs/interceptors/lib/node/index.js new file mode 100644 index 0000000000..caec122add --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/index.js @@ -0,0 +1,39 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkYBN5MFAPjs = require('./chunk-YBN5MFAP.js'); + + + +var _chunkLK6DILFKjs = require('./chunk-LK6DILFK.js'); + + +var _chunk73NOP3T5js = require('./chunk-73NOP3T5.js'); + + + + + + + + +var _chunkWZTE4PCOjs = require('./chunk-WZTE4PCO.js'); + +// src/utils/getCleanUrl.ts +function getCleanUrl(url, isAbsolute = true) { + return [isAbsolute && url.origin, url.pathname].filter(Boolean).join(""); +} + + + + + + + + + + + + + +exports.BatchInterceptor = _chunkYBN5MFAPjs.BatchInterceptor; exports.FetchResponse = _chunkWZTE4PCOjs.FetchResponse; exports.INTERNAL_REQUEST_ID_HEADER_NAME = _chunkWZTE4PCOjs.INTERNAL_REQUEST_ID_HEADER_NAME; exports.IS_PATCHED_MODULE = _chunk73NOP3T5js.IS_PATCHED_MODULE; exports.Interceptor = _chunkWZTE4PCOjs.Interceptor; exports.InterceptorReadyState = _chunkWZTE4PCOjs.InterceptorReadyState; exports.createRequestId = _chunkWZTE4PCOjs.createRequestId; exports.decodeBuffer = _chunkLK6DILFKjs.decodeBuffer; exports.deleteGlobalSymbol = _chunkWZTE4PCOjs.deleteGlobalSymbol; exports.encodeBuffer = _chunkLK6DILFKjs.encodeBuffer; exports.getCleanUrl = getCleanUrl; exports.getGlobalSymbol = _chunkWZTE4PCOjs.getGlobalSymbol; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/index.js.map b/node_modules/@mswjs/interceptors/lib/node/index.js.map new file mode 100644 index 0000000000..ee90ca4d4e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/getCleanUrl.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAGO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE","sourcesContent":["/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/index.mjs b/node_modules/@mswjs/interceptors/lib/node/index.mjs new file mode 100644 index 0000000000..705d150975 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/index.mjs @@ -0,0 +1,39 @@ +import { + BatchInterceptor +} from "./chunk-PJA4E426.mjs"; +import { + decodeBuffer, + encodeBuffer +} from "./chunk-6HYIRFX2.mjs"; +import { + IS_PATCHED_MODULE +} from "./chunk-6YM4PLBI.mjs"; +import { + FetchResponse, + INTERNAL_REQUEST_ID_HEADER_NAME, + Interceptor, + InterceptorReadyState, + createRequestId, + deleteGlobalSymbol, + getGlobalSymbol +} from "./chunk-I7HQIBT7.mjs"; + +// src/utils/getCleanUrl.ts +function getCleanUrl(url, isAbsolute = true) { + return [isAbsolute && url.origin, url.pathname].filter(Boolean).join(""); +} +export { + BatchInterceptor, + FetchResponse, + INTERNAL_REQUEST_ID_HEADER_NAME, + IS_PATCHED_MODULE, + Interceptor, + InterceptorReadyState, + createRequestId, + decodeBuffer, + deleteGlobalSymbol, + encodeBuffer, + getCleanUrl, + getGlobalSymbol +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/index.mjs.map b/node_modules/@mswjs/interceptors/lib/node/index.mjs.map new file mode 100644 index 0000000000..0c277e56ed --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/getCleanUrl.ts"],"sourcesContent":["/**\n * Removes query parameters and hashes from a given URL.\n */\nexport function getCleanUrl(url: URL, isAbsolute: boolean = true): string {\n return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAGO,SAAS,YAAY,KAAU,aAAsB,MAAc;AACxE,SAAO,CAAC,cAAc,IAAI,QAAQ,IAAI,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,EAAE;AACzE;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.d.ts b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.d.ts new file mode 100644 index 0000000000..595d475b3d --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.d.ts @@ -0,0 +1,93 @@ +import { h as Interceptor, H as HttpRequestEventMap } from '../../Interceptor-436630be.js'; +import net from 'node:net'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; +import 'strict-event-emitter'; + +type WriteCallback = (error?: Error | null) => void; + +interface MockSocketOptions { + write: (chunk: Buffer | string, encoding: BufferEncoding | undefined, callback?: WriteCallback) => void; + read: (chunk: Buffer, encoding: BufferEncoding | undefined) => void; +} +declare class MockSocket extends net.Socket { + protected readonly options: MockSocketOptions; + connecting: boolean; + constructor(options: MockSocketOptions); + connect(): this; + write(...args: Array): boolean; + end(...args: Array): this; + push(chunk: any, encoding?: BufferEncoding): boolean; +} + +type HttpConnectionOptions = any; +type MockHttpSocketRequestCallback = (args: { + requestId: string; + request: Request; + socket: MockHttpSocket; +}) => void; +type MockHttpSocketResponseCallback = (args: { + requestId: string; + request: Request; + response: Response; + isMockedResponse: boolean; + socket: MockHttpSocket; +}) => Promise; +interface MockHttpSocketOptions { + connectionOptions: HttpConnectionOptions; + createConnection: () => net.Socket; + onRequest: MockHttpSocketRequestCallback; + onResponse: MockHttpSocketResponseCallback; +} +declare class MockHttpSocket extends MockSocket { + private connectionOptions; + private createConnection; + private baseUrl; + private onRequest; + private onResponse; + private responseListenersPromise?; + private writeBuffer; + private request?; + private requestParser; + private requestStream?; + private shouldKeepAlive?; + private socketState; + private responseParser; + private responseStream?; + private originalSocket?; + constructor(options: MockHttpSocketOptions); + emit(event: string | symbol, ...args: any[]): boolean; + destroy(error?: Error | undefined): this; + /** + * Establish this Socket connection as-is and pipe + * its data/events through this Socket. + */ + passthrough(): void; + /** + * Convert the given Fetch API `Response` instance to an + * HTTP message and push it to the socket. + */ + respondWith(response: Response): Promise; + /** + * Close this socket connection with the given error. + */ + errorWith(error?: Error): void; + private mockConnect; + private flushWriteBuffer; + private onRequestStart; + private onRequestBody; + private onRequestEnd; + private onResponseStart; + private onResponseBody; + private onResponseEnd; +} + +declare class ClientRequestInterceptor extends Interceptor { + static symbol: symbol; + constructor(); + protected setup(): void; + private onRequest; + onResponse: MockHttpSocketResponseCallback; +} + +export { ClientRequestInterceptor }; diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.js b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.js new file mode 100644 index 0000000000..6f5feb35eb --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.js @@ -0,0 +1,9 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunk4IGRW7SKjs = require('../../chunk-4IGRW7SK.js'); +require('../../chunk-6L3PFBGT.js'); +require('../../chunk-WZTE4PCO.js'); + + +exports.ClientRequestInterceptor = _chunk4IGRW7SKjs.ClientRequestInterceptor; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.js.map b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.js.map new file mode 100644 index 0000000000..a464c6732e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.mjs b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.mjs new file mode 100644 index 0000000000..f42854fd79 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.mjs @@ -0,0 +1,9 @@ +import { + ClientRequestInterceptor +} from "../../chunk-QFFDMWKW.mjs"; +import "../../chunk-5KMS5CTP.mjs"; +import "../../chunk-I7HQIBT7.mjs"; +export { + ClientRequestInterceptor +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.mjs.map b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.mjs.map new file mode 100644 index 0000000000..84c51b288c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/ClientRequest/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.d.ts b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.d.ts new file mode 100644 index 0000000000..50659334ff --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.d.ts @@ -0,0 +1,14 @@ +import { Emitter } from 'strict-event-emitter'; +import { H as HttpRequestEventMap, h as Interceptor } from '../../Interceptor-436630be.js'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; + +type XMLHttpRequestEmitter = Emitter; +declare class XMLHttpRequestInterceptor extends Interceptor { + static interceptorSymbol: symbol; + constructor(); + protected checkEnvironment(): boolean; + protected setup(): void; +} + +export { XMLHttpRequestEmitter, XMLHttpRequestInterceptor }; diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.js b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.js new file mode 100644 index 0000000000..5a8eb226c0 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.js @@ -0,0 +1,12 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkLCA4FKWYjs = require('../../chunk-LCA4FKWY.js'); +require('../../chunk-LK6DILFK.js'); +require('../../chunk-PFGO5BSM.js'); +require('../../chunk-73NOP3T5.js'); +require('../../chunk-6L3PFBGT.js'); +require('../../chunk-WZTE4PCO.js'); + + +exports.XMLHttpRequestInterceptor = _chunkLCA4FKWYjs.XMLHttpRequestInterceptor; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.js.map b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.js.map new file mode 100644 index 0000000000..a464c6732e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.mjs b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.mjs new file mode 100644 index 0000000000..be610a7f98 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.mjs @@ -0,0 +1,12 @@ +import { + XMLHttpRequestInterceptor +} from "../../chunk-OMWE7UVM.mjs"; +import "../../chunk-6HYIRFX2.mjs"; +import "../../chunk-TX5GBTFY.mjs"; +import "../../chunk-6YM4PLBI.mjs"; +import "../../chunk-5KMS5CTP.mjs"; +import "../../chunk-I7HQIBT7.mjs"; +export { + XMLHttpRequestInterceptor +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.mjs.map b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.mjs.map new file mode 100644 index 0000000000..84c51b288c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/XMLHttpRequest/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.d.ts b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.d.ts new file mode 100644 index 0000000000..5e40ca5a2b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.d.ts @@ -0,0 +1,13 @@ +import { h as Interceptor, H as HttpRequestEventMap } from '../../Interceptor-436630be.js'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; +import 'strict-event-emitter'; + +declare class FetchInterceptor extends Interceptor { + static symbol: symbol; + constructor(); + protected checkEnvironment(): boolean; + protected setup(): Promise; +} + +export { FetchInterceptor }; diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.js b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.js new file mode 100644 index 0000000000..bcf23a0ded --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.js @@ -0,0 +1,11 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunkLEA3MUU3js = require('../../chunk-LEA3MUU3.js'); +require('../../chunk-PFGO5BSM.js'); +require('../../chunk-73NOP3T5.js'); +require('../../chunk-6L3PFBGT.js'); +require('../../chunk-WZTE4PCO.js'); + + +exports.FetchInterceptor = _chunkLEA3MUU3js.FetchInterceptor; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.js.map b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.js.map new file mode 100644 index 0000000000..a464c6732e --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.mjs b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.mjs new file mode 100644 index 0000000000..033ada34b5 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.mjs @@ -0,0 +1,11 @@ +import { + FetchInterceptor +} from "../../chunk-CTGTMEFD.mjs"; +import "../../chunk-TX5GBTFY.mjs"; +import "../../chunk-6YM4PLBI.mjs"; +import "../../chunk-5KMS5CTP.mjs"; +import "../../chunk-I7HQIBT7.mjs"; +export { + FetchInterceptor +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.mjs.map b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.mjs.map new file mode 100644 index 0000000000..84c51b288c --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/interceptors/fetch/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/presets/node.d.ts b/node_modules/@mswjs/interceptors/lib/node/presets/node.d.ts new file mode 100644 index 0000000000..22cf47470b --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/presets/node.d.ts @@ -0,0 +1,16 @@ +import { ClientRequestInterceptor } from '../interceptors/ClientRequest/index.js'; +import { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest/index.js'; +import { FetchInterceptor } from '../interceptors/fetch/index.js'; +import '../Interceptor-436630be.js'; +import '@open-draft/deferred-promise'; +import '@open-draft/logger'; +import 'strict-event-emitter'; +import 'node:net'; + +/** + * The default preset provisions the interception of requests + * regardless of their type (http/https/XMLHttpRequest). + */ +declare const _default: readonly [ClientRequestInterceptor, XMLHttpRequestInterceptor, FetchInterceptor]; + +export { _default as default }; diff --git a/node_modules/@mswjs/interceptors/lib/node/presets/node.js b/node_modules/@mswjs/interceptors/lib/node/presets/node.js new file mode 100644 index 0000000000..62fde41d6f --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/presets/node.js @@ -0,0 +1,25 @@ +"use strict";Object.defineProperty(exports, "__esModule", {value: true}); + +var _chunk4IGRW7SKjs = require('../chunk-4IGRW7SK.js'); + + +var _chunkLCA4FKWYjs = require('../chunk-LCA4FKWY.js'); +require('../chunk-LK6DILFK.js'); + + +var _chunkLEA3MUU3js = require('../chunk-LEA3MUU3.js'); +require('../chunk-PFGO5BSM.js'); +require('../chunk-73NOP3T5.js'); +require('../chunk-6L3PFBGT.js'); +require('../chunk-WZTE4PCO.js'); + +// src/presets/node.ts +var node_default = [ + new (0, _chunk4IGRW7SKjs.ClientRequestInterceptor)(), + new (0, _chunkLCA4FKWYjs.XMLHttpRequestInterceptor)(), + new (0, _chunkLEA3MUU3js.FetchInterceptor)() +]; + + +exports.default = node_default; +//# sourceMappingURL=node.js.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/presets/node.js.map b/node_modules/@mswjs/interceptors/lib/node/presets/node.js.map new file mode 100644 index 0000000000..a1b2a5c756 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/presets/node.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../../src/presets/node.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAQA,IAAO,eAAQ;AAAA,EACb,IAAI,yBAAyB;AAAA,EAC7B,IAAI,0BAA0B;AAAA,EAC9B,IAAI,iBAAiB;AACvB","sourcesContent":["import { ClientRequestInterceptor } from '../interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest'\nimport { FetchInterceptor } from '../interceptors/fetch'\n\n/**\n * The default preset provisions the interception of requests\n * regardless of their type (http/https/XMLHttpRequest).\n */\nexport default [\n new ClientRequestInterceptor(),\n new XMLHttpRequestInterceptor(),\n new FetchInterceptor(),\n] as const\n"]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/presets/node.mjs b/node_modules/@mswjs/interceptors/lib/node/presets/node.mjs new file mode 100644 index 0000000000..c854677712 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/presets/node.mjs @@ -0,0 +1,25 @@ +import { + ClientRequestInterceptor +} from "../chunk-QFFDMWKW.mjs"; +import { + XMLHttpRequestInterceptor +} from "../chunk-OMWE7UVM.mjs"; +import "../chunk-6HYIRFX2.mjs"; +import { + FetchInterceptor +} from "../chunk-CTGTMEFD.mjs"; +import "../chunk-TX5GBTFY.mjs"; +import "../chunk-6YM4PLBI.mjs"; +import "../chunk-5KMS5CTP.mjs"; +import "../chunk-I7HQIBT7.mjs"; + +// src/presets/node.ts +var node_default = [ + new ClientRequestInterceptor(), + new XMLHttpRequestInterceptor(), + new FetchInterceptor() +]; +export { + node_default as default +}; +//# sourceMappingURL=node.mjs.map \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/lib/node/presets/node.mjs.map b/node_modules/@mswjs/interceptors/lib/node/presets/node.mjs.map new file mode 100644 index 0000000000..188c554323 --- /dev/null +++ b/node_modules/@mswjs/interceptors/lib/node/presets/node.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../../src/presets/node.ts"],"sourcesContent":["import { ClientRequestInterceptor } from '../interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest'\nimport { FetchInterceptor } from '../interceptors/fetch'\n\n/**\n * The default preset provisions the interception of requests\n * regardless of their type (http/https/XMLHttpRequest).\n */\nexport default [\n new ClientRequestInterceptor(),\n new XMLHttpRequestInterceptor(),\n new FetchInterceptor(),\n] as const\n"],"mappings":";;;;;;;;;;;;;;;;AAQA,IAAO,eAAQ;AAAA,EACb,IAAI,yBAAyB;AAAA,EAC7B,IAAI,0BAA0B;AAAA,EAC9B,IAAI,iBAAiB;AACvB;","names":[]} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/package.json b/node_modules/@mswjs/interceptors/package.json new file mode 100644 index 0000000000..14f9528660 --- /dev/null +++ b/node_modules/@mswjs/interceptors/package.json @@ -0,0 +1,202 @@ +{ + "name": "@mswjs/interceptors", + "description": "Low-level HTTP/HTTPS/XHR/fetch request interception library.", + "version": "0.37.5", + "main": "./lib/node/index.js", + "module": "./lib/node/index.mjs", + "types": "./lib/node/index.d.ts", + "exports": { + ".": { + "types": "./lib/node/index.d.ts", + "browser": { + "types": "./lib/browser/index.d.ts", + "require": "./lib/browser/index.js", + "import": "./lib/browser/index.mjs", + "default": "./lib/browser/index.js" + }, + "require": "./lib/node/index.js", + "import": "./lib/node/index.mjs", + "default": "./lib/node/index.js" + }, + "./ClientRequest": { + "types": "./lib/node/interceptors/ClientRequest/index.d.ts", + "node": { + "require": "./lib/node/interceptors/ClientRequest/index.js", + "import": "./lib/node/interceptors/ClientRequest/index.mjs" + }, + "browser": null, + "require": "./lib/node/interceptors/ClientRequest/index.js", + "import": "./lib/node/interceptors/ClientRequest/index.mjs", + "default": "./lib/node/interceptors/ClientRequest/index.js" + }, + "./XMLHttpRequest": { + "browser": { + "types": "./lib/browser/interceptors/XMLHttpRequest/index.d.ts", + "require": "./lib/browser/interceptors/XMLHttpRequest/index.js", + "import": "./lib/browser/interceptors/XMLHttpRequest/index.mjs", + "default": "./lib/browser/interceptors/XMLHttpRequest/index.js" + }, + "types": "./lib/node/interceptors/XMLHttpRequest/index.d.ts", + "require": "./lib/node/interceptors/XMLHttpRequest/index.js", + "import": "./lib/node/interceptors/XMLHttpRequest/index.mjs", + "default": "./lib/node/interceptors/XMLHttpRequest/index.js" + }, + "./fetch": { + "browser": { + "types": "./lib/browser/interceptors/fetch/index.d.ts", + "require": "./lib/browser/interceptors/fetch/index.js", + "import": "./lib/browser/interceptors/fetch/index.mjs", + "default": "./lib/browser/interceptors/fetch/index.js" + }, + "types": "./lib/node/interceptors/fetch/index.d.ts", + "require": "./lib/node/interceptors/fetch/index.js", + "import": "./lib/node/interceptors/fetch/index.mjs", + "default": "./lib/node/interceptors/fetch/index.js" + }, + "./WebSocket": { + "types": "./lib/browser/interceptors/WebSocket/index.d.ts", + "require": "./lib/browser/interceptors/WebSocket/index.js", + "import": "./lib/browser/interceptors/WebSocket/index.mjs", + "default": "./lib/browser/interceptors/WebSocket/index.js" + }, + "./RemoteHttpInterceptor": { + "types": "./lib/node/RemoteHttpInterceptor.d.ts", + "node": { + "require": "./lib/node/RemoteHttpInterceptor.js", + "import": "./lib/node/RemoteHttpInterceptor.mjs" + }, + "browser": null, + "require": "./lib/node/RemoteHttpInterceptor.js", + "import": "./lib/node/RemoteHttpInterceptor.mjs", + "default": "./lib/node/RemoteHttpInterceptor.js" + }, + "./presets/node": { + "types": "./lib/node/presets/node.d.ts", + "node": { + "require": "./lib/node/presets/node.js", + "import": "./lib/node/presets/node.mjs" + }, + "browser": null, + "require": "./lib/node/presets/node.js", + "import": "./lib/node/presets/node.mjs", + "default": "./lib/node/presets/node.js" + }, + "./presets/browser": { + "browser": { + "types": "./lib/browser/presets/browser.d.ts", + "require": "./lib/browser/presets/browser.js", + "import": "./lib/browser/presets/browser.mjs", + "default": "./lib/browser/presets/browser.js" + } + } + }, + "author": "Artem Zakharchenko", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "files": [ + "lib", + "README.md", + "src", + "ClientRequest", + "fetch", + "RemoteHttpInterceptor", + "XMLHttpRequest", + "WebSocket" + ], + "repository": { + "type": "git", + "url": "https://github.com/mswjs/interceptors" + }, + "devDependencies": { + "@commitlint/cli": "^16.0.2", + "@commitlint/config-conventional": "^16.0.0", + "@open-draft/test-server": "^0.5.1", + "@ossjs/release": "^0.8.1", + "@playwright/test": "^1.37.1", + "@types/cors": "^2.8.12", + "@types/express": "^4.17.13", + "@types/express-fileupload": "^1.5.0", + "@types/express-rate-limit": "^6.0.0", + "@types/follow-redirects": "^1.14.1", + "@types/jest": "^27.0.3", + "@types/node": "^18.19.31", + "@types/node-fetch": "2.5.12", + "@types/superagent": "^8.1.9", + "@types/supertest": "^2.0.11", + "@types/ws": "^8.5.10", + "axios": "^1.6.0", + "body-parser": "^1.19.0", + "commitizen": "^4.2.4", + "cors": "^2.8.5", + "cross-env": "^7.0.3", + "cz-conventional-changelog": "3.3.0", + "engine.io-parser": "^5.2.1", + "express": "^4.17.3", + "express-fileupload": "^1.5.1", + "express-rate-limit": "^6.3.0", + "follow-redirects": "^1.15.1", + "got": "^11.8.3", + "happy-dom": "^12.10.3", + "jest": "^27.4.3", + "node-fetch": "2.6.7", + "rimraf": "^3.0.2", + "simple-git-hooks": "^2.7.0", + "socket.io": "^4.7.4", + "socket.io-client": "^4.7.4", + "socket.io-parser": "^4.2.4", + "superagent": "^10.1.1", + "supertest": "^6.1.6", + "ts-jest": "^27.1.1", + "tsup": "^6.5.0", + "typescript": "^4.9.4", + "undici": "^6.6.2", + "vitest": "^1.2.2", + "vitest-environment-miniflare": "^2.14.1", + "wait-for-expect": "^3.0.2", + "web-encoding": "^1.1.5", + "webpack-http-server": "^0.5.0", + "ws": "^8.16.0" + }, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "resolutions": { + "memfs": "^3.4.13" + }, + "keywords": [ + "request", + "intercept", + "http", + "https", + "xmlhttprequest", + "xhr", + "fetch", + "low-level", + "mock", + "spy", + "testing" + ], + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } + }, + "scripts": { + "start": "tsc --build -w", + "test": "pnpm test:unit && pnpm test:integration", + "test:unit": "vitest", + "test:integration": "pnpm test:node && pnpm test:browser", + "test:node": "vitest -c test/vitest.config.js", + "test:browser": "pnpm playwright test -c test/playwright.config.ts", + "clean": "rimraf lib", + "build": "pnpm clean && cross-env NODE_ENV=production tsup --splitting", + "release": "release publish" + } +} \ No newline at end of file diff --git a/node_modules/@mswjs/interceptors/src/BatchInterceptor.test.ts b/node_modules/@mswjs/interceptors/src/BatchInterceptor.test.ts new file mode 100644 index 0000000000..5891d62671 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/BatchInterceptor.test.ts @@ -0,0 +1,255 @@ +import { vi, it, expect, afterEach } from 'vitest' +import { Interceptor } from './Interceptor' +import { BatchInterceptor } from './BatchInterceptor' + +afterEach(() => { + vi.resetAllMocks() +}) + +it('applies child interceptors', () => { + class PrimaryInterceptor extends Interceptor { + constructor() { + super(Symbol('primary')) + } + } + + class SecondaryInterceptor extends Interceptor { + constructor() { + super(Symbol('secondary')) + } + } + + const instances = { + primary: new PrimaryInterceptor(), + secondary: new SecondaryInterceptor(), + } + + const interceptor = new BatchInterceptor({ + name: 'batch-apply', + interceptors: [instances.primary, instances.secondary], + }) + + const primaryApplySpy = vi.spyOn(instances.primary, 'apply') + const secondaryApplySpy = vi.spyOn(instances.secondary, 'apply') + + interceptor.apply() + + expect(primaryApplySpy).toHaveBeenCalledTimes(1) + expect(secondaryApplySpy).toHaveBeenCalledTimes(1) +}) + +it('proxies event listeners to the interceptors', () => { + class PrimaryInterceptor extends Interceptor<{ hello: [string] }> { + constructor() { + super(Symbol('primary')) + } + } + + class SecondaryInterceptor extends Interceptor<{ + goodbye: [string] + }> { + constructor() { + super(Symbol('secondary')) + } + } + + const instances = { + primary: new PrimaryInterceptor(), + secondary: new SecondaryInterceptor(), + } + + const interceptor = new BatchInterceptor({ + name: 'batch-proxy', + interceptors: [instances.primary, instances.secondary], + }) + + const helloListener = vi.fn() + interceptor.on('hello', helloListener) + + const goodbyeListener = vi.fn() + interceptor.on('goodbye', goodbyeListener) + + // Emulate the child interceptor emitting events. + instances.primary['emitter'].emit('hello', 'John') + instances.secondary['emitter'].emit('goodbye', 'Kate') + + // Must call the batch interceptor listener. + expect(helloListener).toHaveBeenCalledTimes(1) + expect(helloListener).toHaveBeenCalledWith('John') + expect(goodbyeListener).toHaveBeenCalledTimes(1) + expect(goodbyeListener).toHaveBeenCalledWith('Kate') +}) + +it('disposes of child interceptors', async () => { + class PrimaryInterceptor extends Interceptor { + constructor() { + super(Symbol('primary')) + } + } + + class SecondaryInterceptor extends Interceptor { + constructor() { + super(Symbol('secondary')) + } + } + + const instances = { + primary: new PrimaryInterceptor(), + secondary: new SecondaryInterceptor(), + } + + const interceptor = new BatchInterceptor({ + name: 'batch-dispose', + interceptors: [instances.primary, instances.secondary], + }) + + const primaryDisposeSpy = vi.spyOn(instances.primary, 'dispose') + const secondaryDisposeSpy = vi.spyOn(instances.secondary, 'dispose') + + interceptor.apply() + interceptor.dispose() + + expect(primaryDisposeSpy).toHaveBeenCalledTimes(1) + expect(secondaryDisposeSpy).toHaveBeenCalledTimes(1) +}) + +it('forwards listeners added via "on()"', () => { + class FirstInterceptor extends Interceptor { + constructor() { + super(Symbol('first')) + } + } + class SecondaryInterceptor extends Interceptor { + constructor() { + super(Symbol('second')) + } + } + + const firstInterceptor = new FirstInterceptor() + const secondInterceptor = new SecondaryInterceptor() + + const interceptor = new BatchInterceptor({ + name: 'batch', + interceptors: [firstInterceptor, secondInterceptor], + }) + + const listener = vi.fn() + interceptor.on('foo', listener) + + expect(firstInterceptor['emitter'].listenerCount('foo')).toBe(1) + expect(secondInterceptor['emitter'].listenerCount('foo')).toBe(1) + expect(interceptor['emitter'].listenerCount('foo')).toBe(0) +}) + +it('forwards listeners removal via "off()"', () => { + type Events = { + foo: [] + } + + class FirstInterceptor extends Interceptor { + constructor() { + super(Symbol('first')) + } + } + class SecondaryInterceptor extends Interceptor { + constructor() { + super(Symbol('second')) + } + } + + const firstInterceptor = new FirstInterceptor() + const secondInterceptor = new SecondaryInterceptor() + + const interceptor = new BatchInterceptor({ + name: 'batch', + interceptors: [firstInterceptor, secondInterceptor], + }) + + const listener = vi.fn() + interceptor.on('foo', listener) + interceptor.off('foo', listener) + + expect(firstInterceptor['emitter'].listenerCount('foo')).toBe(0) + expect(secondInterceptor['emitter'].listenerCount('foo')).toBe(0) +}) + +it('forwards removal of all listeners by name via ".removeAllListeners()"', () => { + type Events = { + foo: [] + bar: [] + } + + class FirstInterceptor extends Interceptor { + constructor() { + super(Symbol('first')) + } + } + class SecondaryInterceptor extends Interceptor { + constructor() { + super(Symbol('second')) + } + } + + const firstInterceptor = new FirstInterceptor() + const secondInterceptor = new SecondaryInterceptor() + + const interceptor = new BatchInterceptor({ + name: 'batch', + interceptors: [firstInterceptor, secondInterceptor], + }) + + const listener = vi.fn() + interceptor.on('foo', listener) + interceptor.on('foo', listener) + interceptor.on('bar', listener) + + expect(firstInterceptor['emitter'].listenerCount('foo')).toBe(2) + expect(secondInterceptor['emitter'].listenerCount('foo')).toBe(2) + expect(firstInterceptor['emitter'].listenerCount('bar')).toBe(1) + expect(secondInterceptor['emitter'].listenerCount('bar')).toBe(1) + + interceptor.removeAllListeners('foo') + + expect(firstInterceptor['emitter'].listenerCount('foo')).toBe(0) + expect(secondInterceptor['emitter'].listenerCount('foo')).toBe(0) + expect(firstInterceptor['emitter'].listenerCount('bar')).toBe(1) + expect(secondInterceptor['emitter'].listenerCount('bar')).toBe(1) +}) + +it('forwards removal of all listeners via ".removeAllListeners()"', () => { + class FirstInterceptor extends Interceptor { + constructor() { + super(Symbol('first')) + } + } + class SecondaryInterceptor extends Interceptor { + constructor() { + super(Symbol('second')) + } + } + + const firstInterceptor = new FirstInterceptor() + const secondInterceptor = new SecondaryInterceptor() + + const interceptor = new BatchInterceptor({ + name: 'batch', + interceptors: [firstInterceptor, secondInterceptor], + }) + + const listener = vi.fn() + interceptor.on('foo', listener) + interceptor.on('foo', listener) + interceptor.on('bar', listener) + + expect(firstInterceptor['emitter'].listenerCount('foo')).toBe(2) + expect(secondInterceptor['emitter'].listenerCount('foo')).toBe(2) + expect(firstInterceptor['emitter'].listenerCount('bar')).toBe(1) + expect(secondInterceptor['emitter'].listenerCount('bar')).toBe(1) + + interceptor.removeAllListeners() + + expect(firstInterceptor['emitter'].listenerCount('foo')).toBe(0) + expect(secondInterceptor['emitter'].listenerCount('foo')).toBe(0) + expect(firstInterceptor['emitter'].listenerCount('bar')).toBe(0) + expect(secondInterceptor['emitter'].listenerCount('bar')).toBe(0) +}) diff --git a/node_modules/@mswjs/interceptors/src/BatchInterceptor.ts b/node_modules/@mswjs/interceptors/src/BatchInterceptor.ts new file mode 100644 index 0000000000..083ce5fb23 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/BatchInterceptor.ts @@ -0,0 +1,95 @@ +import { EventMap, Listener } from 'strict-event-emitter' +import { Interceptor, ExtractEventNames } from './Interceptor' + +export interface BatchInterceptorOptions< + InterceptorList extends ReadonlyArray> +> { + name: string + interceptors: InterceptorList +} + +export type ExtractEventMapType< + InterceptorList extends ReadonlyArray> +> = InterceptorList extends ReadonlyArray + ? InterceptorType extends Interceptor + ? EventMap + : never + : never + +/** + * A batch interceptor that exposes a single interface + * to apply and operate with multiple interceptors at once. + */ +export class BatchInterceptor< + InterceptorList extends ReadonlyArray>, + Events extends EventMap = ExtractEventMapType +> extends Interceptor { + static symbol: symbol + + private interceptors: InterceptorList + + constructor(options: BatchInterceptorOptions) { + BatchInterceptor.symbol = Symbol(options.name) + super(BatchInterceptor.symbol) + this.interceptors = options.interceptors + } + + protected setup() { + const logger = this.logger.extend('setup') + + logger.info('applying all %d interceptors...', this.interceptors.length) + + for (const interceptor of this.interceptors) { + logger.info('applying "%s" interceptor...', interceptor.constructor.name) + interceptor.apply() + + logger.info('adding interceptor dispose subscription') + this.subscriptions.push(() => interceptor.dispose()) + } + } + + public on>( + event: EventName, + listener: Listener + ): this { + // Instead of adding a listener to the batch interceptor, + // propagate the listener to each of the individual interceptors. + for (const interceptor of this.interceptors) { + interceptor.on(event, listener) + } + + return this + } + + public once>( + event: EventName, + listener: Listener + ): this { + for (const interceptor of this.interceptors) { + interceptor.once(event, listener) + } + + return this + } + + public off>( + event: EventName, + listener: Listener + ): this { + for (const interceptor of this.interceptors) { + interceptor.off(event, listener) + } + + return this + } + + public removeAllListeners>( + event?: EventName | undefined + ): this { + for (const interceptors of this.interceptors) { + interceptors.removeAllListeners(event) + } + + return this + } +} diff --git a/node_modules/@mswjs/interceptors/src/Interceptor.test.ts b/node_modules/@mswjs/interceptors/src/Interceptor.test.ts new file mode 100644 index 0000000000..6b76606a55 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/Interceptor.test.ts @@ -0,0 +1,205 @@ +import { describe, vi, it, expect, afterEach } from 'vitest' +import { + Interceptor, + getGlobalSymbol, + deleteGlobalSymbol, + InterceptorReadyState, +} from './Interceptor' +import { nextTickAsync } from './utils/nextTick' + +const symbol = Symbol('test') + +afterEach(() => { + deleteGlobalSymbol(symbol) +}) + +it('does not set a maximum listeners limit', () => { + const interceptor = new Interceptor(symbol) + expect(interceptor['emitter'].getMaxListeners()).toBe(0) +}) + +describe('on()', () => { + it('adds a new listener using "on()"', () => { + const interceptor = new Interceptor(symbol) + expect(interceptor['emitter'].listenerCount('event')).toBe(0) + + const listener = vi.fn() + interceptor.on('event', listener) + expect(interceptor['emitter'].listenerCount('event')).toBe(1) + }) +}) + +describe('once()', () => { + it('calls the listener only once', () => { + const interceptor = new Interceptor(symbol) + const listener = vi.fn() + + interceptor.once('foo', listener) + expect(listener).not.toHaveBeenCalled() + + interceptor['emitter'].emit('foo', 'bar') + + expect(listener).toHaveBeenCalledTimes(1) + expect(listener).toHaveBeenCalledWith('bar') + + listener.mockReset() + + interceptor['emitter'].emit('foo', 'baz') + interceptor['emitter'].emit('foo', 'xyz') + expect(listener).toHaveBeenCalledTimes(0) + }) +}) + +describe('off()', () => { + it('removes a listener using "off()"', () => { + const interceptor = new Interceptor(symbol) + expect(interceptor['emitter'].listenerCount('event')).toBe(0) + + const listener = vi.fn() + interceptor.on('event', listener) + expect(interceptor['emitter'].listenerCount('event')).toBe(1) + + interceptor.off('event', listener) + expect(interceptor['emitter'].listenerCount('event')).toBe(0) + }) +}) + +describe('persistence', () => { + it('stores global reference to the applied interceptor', () => { + const interceptor = new Interceptor(symbol) + interceptor.apply() + + expect(getGlobalSymbol(symbol)).toEqual(interceptor) + }) + + it('deletes global reference when the interceptor is disposed', () => { + const interceptor = new Interceptor(symbol) + + interceptor.apply() + interceptor.dispose() + + expect(getGlobalSymbol(symbol)).toBeUndefined() + }) +}) + +describe('readyState', () => { + it('sets the state to "INACTIVE" when the interceptor is created', () => { + const interceptor = new Interceptor(symbol) + expect(interceptor.readyState).toBe(InterceptorReadyState.INACTIVE) + }) + + it('leaves state as "INACTIVE" if the interceptor failed the environment check', async () => { + class MyInterceptor extends Interceptor { + protected checkEnvironment(): boolean { + return false + } + } + const interceptor = new MyInterceptor(symbol) + interceptor.apply() + + expect(interceptor.readyState).toBe(InterceptorReadyState.INACTIVE) + }) + + it('perfroms state transition when the interceptor is applying', async () => { + const interceptor = new Interceptor(symbol) + interceptor.apply() + + // The interceptor's state transitions to APPLIED immediately. + // The only exception is if something throws during the setup. + expect(interceptor.readyState).toBe(InterceptorReadyState.APPLIED) + }) + + it('perfroms state transition when disposing of the interceptor', async () => { + const interceptor = new Interceptor(symbol) + interceptor.apply() + interceptor.dispose() + + // The interceptor's state transitions to DISPOSED immediately. + // The only exception is if something throws during the teardown. + expect(interceptor.readyState).toBe(InterceptorReadyState.DISPOSED) + }) +}) + +describe('apply', () => { + it('does not apply the same interceptor multiple times', () => { + const interceptor = new Interceptor(symbol) + const setupSpy = vi.spyOn( + interceptor, + // @ts-expect-error Protected property spy. + 'setup' + ) + + // Intentionally apply the same interceptor multiple times. + interceptor.apply() + interceptor.apply() + interceptor.apply() + + // The "setup" must not be called repeatedly. + expect(setupSpy).toHaveBeenCalledTimes(1) + + expect(getGlobalSymbol(symbol)).toEqual(interceptor) + }) + + it('does not call "apply" if the interceptor fails environment check', () => { + class MyInterceptor extends Interceptor<{}> { + checkEnvironment() { + return false + } + } + + const interceptor = new MyInterceptor(Symbol('test')) + const setupSpy = vi.spyOn( + interceptor, + // @ts-expect-error Protected property spy. + 'setup' + ) + interceptor.apply() + + expect(setupSpy).not.toHaveBeenCalled() + }) + + it('proxies listeners from new interceptor to already running interceptor', () => { + const firstInterceptor = new Interceptor(symbol) + const secondInterceptor = new Interceptor(symbol) + + firstInterceptor.apply() + const firstListener = vi.fn() + firstInterceptor.on('test', firstListener) + + secondInterceptor.apply() + const secondListener = vi.fn() + secondInterceptor.on('test', secondListener) + + // Emitting event in the first interceptor will bubble to the second one. + firstInterceptor['emitter'].emit('test', 'hello world') + + expect(firstListener).toHaveBeenCalledTimes(1) + expect(firstListener).toHaveBeenCalledWith('hello world') + + expect(secondListener).toHaveBeenCalledTimes(1) + expect(secondListener).toHaveBeenCalledWith('hello world') + + expect(secondInterceptor['emitter'].listenerCount('test')).toBe(0) + }) +}) + +describe('dispose', () => { + it('removes all listeners when the interceptor is disposed', async () => { + const interceptor = new Interceptor(symbol) + + interceptor.apply() + const listener = vi.fn() + interceptor.on('test', listener) + interceptor.dispose() + + // Even after emitting an event, the listener must not get called. + interceptor['emitter'].emit('test') + expect(listener).not.toHaveBeenCalled() + + // The listener must not be called on the next tick either. + await nextTickAsync(() => { + interceptor['emitter'].emit('test') + expect(listener).not.toHaveBeenCalled() + }) + }) +}) diff --git a/node_modules/@mswjs/interceptors/src/Interceptor.ts b/node_modules/@mswjs/interceptors/src/Interceptor.ts new file mode 100644 index 0000000000..b33e74fdfb --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/Interceptor.ts @@ -0,0 +1,249 @@ +import { Logger } from '@open-draft/logger' +import { Emitter, Listener } from 'strict-event-emitter' + +export type InterceptorEventMap = Record +export type InterceptorSubscription = () => void + +/** + * Request header name to detect when a single request + * is being handled by nested interceptors (XHR -> ClientRequest). + * Obscure by design to prevent collisions with user-defined headers. + * Ideally, come up with the Interceptor-level mechanism for this. + * @see https://github.com/mswjs/interceptors/issues/378 + */ +export const INTERNAL_REQUEST_ID_HEADER_NAME = + 'x-interceptors-internal-request-id' + +export function getGlobalSymbol(symbol: Symbol): V | undefined { + return ( + // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587 + globalThis[symbol] || undefined + ) +} + +function setGlobalSymbol(symbol: Symbol, value: any): void { + // @ts-ignore + globalThis[symbol] = value +} + +export function deleteGlobalSymbol(symbol: Symbol): void { + // @ts-ignore + delete globalThis[symbol] +} + +export enum InterceptorReadyState { + INACTIVE = 'INACTIVE', + APPLYING = 'APPLYING', + APPLIED = 'APPLIED', + DISPOSING = 'DISPOSING', + DISPOSED = 'DISPOSED', +} + +export type ExtractEventNames> = + Events extends Record ? EventName : never + +export class Interceptor { + protected emitter: Emitter + protected subscriptions: Array + protected logger: Logger + + public readyState: InterceptorReadyState + + constructor(private readonly symbol: symbol) { + this.readyState = InterceptorReadyState.INACTIVE + + this.emitter = new Emitter() + this.subscriptions = [] + this.logger = new Logger(symbol.description!) + + // Do not limit the maximum number of listeners + // so not to limit the maximum amount of parallel events emitted. + this.emitter.setMaxListeners(0) + + this.logger.info('constructing the interceptor...') + } + + /** + * Determine if this interceptor can be applied + * in the current environment. + */ + protected checkEnvironment(): boolean { + return true + } + + /** + * Apply this interceptor to the current process. + * Returns an already running interceptor instance if it's present. + */ + public apply(): void { + const logger = this.logger.extend('apply') + logger.info('applying the interceptor...') + + if (this.readyState === InterceptorReadyState.APPLIED) { + logger.info('intercepted already applied!') + return + } + + const shouldApply = this.checkEnvironment() + + if (!shouldApply) { + logger.info('the interceptor cannot be applied in this environment!') + return + } + + this.readyState = InterceptorReadyState.APPLYING + + // Whenever applying a new interceptor, check if it hasn't been applied already. + // This enables to apply the same interceptor multiple times, for example from a different + // interceptor, only proxying events but keeping the stubs in a single place. + const runningInstance = this.getInstance() + + if (runningInstance) { + logger.info('found a running instance, reusing...') + + // Proxy any listeners you set on this instance to the running instance. + this.on = (event, listener) => { + logger.info('proxying the "%s" listener', event) + + // Add listeners to the running instance so they appear + // at the top of the event listeners list and are executed first. + runningInstance.emitter.addListener(event, listener) + + // Ensure that once this interceptor instance is disposed, + // it removes all listeners it has appended to the running interceptor instance. + this.subscriptions.push(() => { + runningInstance.emitter.removeListener(event, listener) + logger.info('removed proxied "%s" listener!', event) + }) + + return this + } + + this.readyState = InterceptorReadyState.APPLIED + + return + } + + logger.info('no running instance found, setting up a new instance...') + + // Setup the interceptor. + this.setup() + + // Store the newly applied interceptor instance globally. + this.setInstance() + + this.readyState = InterceptorReadyState.APPLIED + } + + /** + * Setup the module augments and stubs necessary for this interceptor. + * This method is not run if there's a running interceptor instance + * to prevent instantiating an interceptor multiple times. + */ + protected setup(): void {} + + /** + * Listen to the interceptor's public events. + */ + public on>( + event: EventName, + listener: Listener + ): this { + const logger = this.logger.extend('on') + + if ( + this.readyState === InterceptorReadyState.DISPOSING || + this.readyState === InterceptorReadyState.DISPOSED + ) { + logger.info('cannot listen to events, already disposed!') + return this + } + + logger.info('adding "%s" event listener:', event, listener) + + this.emitter.on(event, listener) + return this + } + + public once>( + event: EventName, + listener: Listener + ): this { + this.emitter.once(event, listener) + return this + } + + public off>( + event: EventName, + listener: Listener + ): this { + this.emitter.off(event, listener) + return this + } + + public removeAllListeners>( + event?: EventName + ): this { + this.emitter.removeAllListeners(event) + return this + } + + /** + * Disposes of any side-effects this interceptor has introduced. + */ + public dispose(): void { + const logger = this.logger.extend('dispose') + + if (this.readyState === InterceptorReadyState.DISPOSED) { + logger.info('cannot dispose, already disposed!') + return + } + + logger.info('disposing the interceptor...') + this.readyState = InterceptorReadyState.DISPOSING + + if (!this.getInstance()) { + logger.info('no interceptors running, skipping dispose...') + return + } + + // Delete the global symbol as soon as possible, + // indicating that the interceptor is no longer running. + this.clearInstance() + + logger.info('global symbol deleted:', getGlobalSymbol(this.symbol)) + + if (this.subscriptions.length > 0) { + logger.info('disposing of %d subscriptions...', this.subscriptions.length) + + for (const dispose of this.subscriptions) { + dispose() + } + + this.subscriptions = [] + + logger.info('disposed of all subscriptions!', this.subscriptions.length) + } + + this.emitter.removeAllListeners() + logger.info('destroyed the listener!') + + this.readyState = InterceptorReadyState.DISPOSED + } + + private getInstance(): this | undefined { + const instance = getGlobalSymbol(this.symbol) + this.logger.info('retrieved global instance:', instance?.constructor?.name) + return instance + } + + private setInstance(): void { + setGlobalSymbol(this.symbol, this) + this.logger.info('set global instance!', this.symbol.description) + } + + private clearInstance(): void { + deleteGlobalSymbol(this.symbol) + this.logger.info('cleared global instance!', this.symbol.description) + } +} diff --git a/node_modules/@mswjs/interceptors/src/InterceptorError.ts b/node_modules/@mswjs/interceptors/src/InterceptorError.ts new file mode 100644 index 0000000000..882848befd --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/InterceptorError.ts @@ -0,0 +1,7 @@ +export class InterceptorError extends Error { + constructor(message?: string) { + super(message) + this.name = 'InterceptorError' + Object.setPrototypeOf(this, InterceptorError.prototype) + } +} diff --git a/node_modules/@mswjs/interceptors/src/RemoteHttpInterceptor.ts b/node_modules/@mswjs/interceptors/src/RemoteHttpInterceptor.ts new file mode 100644 index 0000000000..5b7c53dca1 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/RemoteHttpInterceptor.ts @@ -0,0 +1,244 @@ +import { ChildProcess } from 'child_process' +import { HttpRequestEventMap } from './glossary' +import { Interceptor } from './Interceptor' +import { BatchInterceptor } from './BatchInterceptor' +import { ClientRequestInterceptor } from './interceptors/ClientRequest' +import { XMLHttpRequestInterceptor } from './interceptors/XMLHttpRequest' +import { handleRequest } from './utils/handleRequest' +import { RequestController } from './RequestController' +import { FetchResponse } from './utils/fetchUtils' + +export interface SerializedRequest { + id: string + url: string + method: string + headers: Array<[string, string]> + credentials: RequestCredentials + body: string +} + +interface RevivedRequest extends Omit { + url: URL + headers: Headers +} + +export interface SerializedResponse { + status: number + statusText: string + headers: Array<[string, string]> + body: string +} + +export class RemoteHttpInterceptor extends BatchInterceptor< + [ClientRequestInterceptor, XMLHttpRequestInterceptor] +> { + constructor() { + super({ + name: 'remote-interceptor', + interceptors: [ + new ClientRequestInterceptor(), + new XMLHttpRequestInterceptor(), + ], + }) + } + + protected setup() { + super.setup() + + let handleParentMessage: NodeJS.MessageListener + + this.on('request', async ({ request, requestId, controller }) => { + // Send the stringified intercepted request to + // the parent process where the remote resolver is established. + const serializedRequest = JSON.stringify({ + id: requestId, + method: request.method, + url: request.url, + headers: Array.from(request.headers.entries()), + credentials: request.credentials, + body: ['GET', 'HEAD'].includes(request.method) + ? null + : await request.text(), + } as SerializedRequest) + + this.logger.info( + 'sent serialized request to the child:', + serializedRequest + ) + + process.send?.(`request:${serializedRequest}`) + + const responsePromise = new Promise((resolve) => { + handleParentMessage = (message) => { + if (typeof message !== 'string') { + return resolve() + } + + if (message.startsWith(`response:${requestId}`)) { + const [, serializedResponse] = + message.match(/^response:.+?:(.+)$/) || [] + + if (!serializedResponse) { + return resolve() + } + + const responseInit = JSON.parse( + serializedResponse + ) as SerializedResponse + + const mockedResponse = new FetchResponse(responseInit.body, { + url: request.url, + status: responseInit.status, + statusText: responseInit.statusText, + headers: responseInit.headers, + }) + + /** + * @todo Support "errorWith" as well. + * This response handling from the child is incomplete. + */ + + controller.respondWith(mockedResponse) + return resolve() + } + } + }) + + // Listen for the mocked response message from the parent. + this.logger.info( + 'add "message" listener to the parent process', + handleParentMessage + ) + process.addListener('message', handleParentMessage) + + return responsePromise + }) + + this.subscriptions.push(() => { + process.removeListener('message', handleParentMessage) + }) + } +} + +export function requestReviver(key: string, value: any) { + switch (key) { + case 'url': + return new URL(value) + + case 'headers': + return new Headers(value) + + default: + return value + } +} + +export interface RemoveResolverOptions { + process: ChildProcess +} + +export class RemoteHttpResolver extends Interceptor { + static symbol = Symbol('remote-resolver') + private process: ChildProcess + + constructor(options: RemoveResolverOptions) { + super(RemoteHttpResolver.symbol) + this.process = options.process + } + + protected setup() { + const logger = this.logger.extend('setup') + + const handleChildMessage: NodeJS.MessageListener = async (message) => { + logger.info('received message from child!', message) + + if (typeof message !== 'string' || !message.startsWith('request:')) { + logger.info('unknown message, ignoring...') + return + } + + const [, serializedRequest] = message.match(/^request:(.+)$/) || [] + if (!serializedRequest) { + return + } + + const requestJson = JSON.parse( + serializedRequest, + requestReviver + ) as RevivedRequest + + logger.info('parsed intercepted request', requestJson) + + const request = new Request(requestJson.url, { + method: requestJson.method, + headers: new Headers(requestJson.headers), + credentials: requestJson.credentials, + body: requestJson.body, + }) + + const controller = new RequestController(request) + await handleRequest({ + request, + requestId: requestJson.id, + controller, + emitter: this.emitter, + onResponse: async (response) => { + this.logger.info('received mocked response!', { response }) + + const responseClone = response.clone() + const responseText = await responseClone.text() + + // // Send the mocked response to the child process. + const serializedResponse = JSON.stringify({ + status: response.status, + statusText: response.statusText, + headers: Array.from(response.headers.entries()), + body: responseText, + } as SerializedResponse) + + this.process.send( + `response:${requestJson.id}:${serializedResponse}`, + (error) => { + if (error) { + return + } + + // Emit an optimistic "response" event at this point, + // not to rely on the back-and-forth signaling for the sake of the event. + this.emitter.emit('response', { + request, + requestId: requestJson.id, + response: responseClone, + isMockedResponse: true, + }) + } + ) + + logger.info( + 'sent serialized mocked response to the parent:', + serializedResponse + ) + }, + onRequestError: (response) => { + this.logger.info('received a network error!', { response }) + throw new Error('Not implemented') + }, + onError: (error) => { + this.logger.info('request has errored!', { error }) + throw new Error('Not implemented') + }, + }) + } + + this.subscriptions.push(() => { + this.process.removeListener('message', handleChildMessage) + logger.info('removed the "message" listener from the child process!') + }) + + logger.info('adding a "message" listener to the child process') + this.process.addListener('message', handleChildMessage) + + this.process.once('error', () => this.dispose()) + this.process.once('exit', () => this.dispose()) + } +} diff --git a/node_modules/@mswjs/interceptors/src/RequestController.test.ts b/node_modules/@mswjs/interceptors/src/RequestController.test.ts new file mode 100644 index 0000000000..f3adeab2a3 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/RequestController.test.ts @@ -0,0 +1,49 @@ +import { it, expect } from 'vitest' +import { kResponsePromise, RequestController } from './RequestController' + +it('creates a pending response promise on construction', () => { + const controller = new RequestController(new Request('http://localhost')) + expect(controller[kResponsePromise]).toBeInstanceOf(Promise) + expect(controller[kResponsePromise].state).toBe('pending') +}) + +it('resolves the response promise with the response provided to "respondWith"', async () => { + const controller = new RequestController(new Request('http://localhost')) + controller.respondWith(new Response('hello world')) + + const response = (await controller[kResponsePromise]) as Response + + expect(response).toBeInstanceOf(Response) + expect(response.status).toBe(200) + expect(await response.text()).toBe('hello world') +}) + +it('resolves the response promise with the error provided to "errorWith"', async () => { + const controller = new RequestController(new Request('http://localhost')) + const error = new Error('Oops!') + controller.errorWith(error) + + await expect(controller[kResponsePromise]).resolves.toEqual(error) +}) + +it('throws when calling "respondWith" multiple times', () => { + const controller = new RequestController(new Request('http://localhost')) + controller.respondWith(new Response('hello world')) + + expect(() => { + controller.respondWith(new Response('second response')) + }).toThrow( + 'Failed to respond to the "GET http://localhost/" request: the "request" event has already been handled.' + ) +}) + +it('throws when calling "errorWith" multiple times', () => { + const controller = new RequestController(new Request('http://localhost')) + controller.errorWith(new Error('Oops!')) + + expect(() => { + controller.errorWith(new Error('second error')) + }).toThrow( + 'Failed to error the "GET http://localhost/" request: the "request" event has already been handled.' + ) +}) diff --git a/node_modules/@mswjs/interceptors/src/RequestController.ts b/node_modules/@mswjs/interceptors/src/RequestController.ts new file mode 100644 index 0000000000..8ff48cfcdd --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/RequestController.ts @@ -0,0 +1,81 @@ +import { invariant } from 'outvariant' +import { DeferredPromise } from '@open-draft/deferred-promise' +import { InterceptorError } from './InterceptorError' + +const kRequestHandled = Symbol('kRequestHandled') +export const kResponsePromise = Symbol('kResponsePromise') + +export class RequestController { + /** + * Internal response promise. + * Available only for the library internals to grab the + * response instance provided by the developer. + * @note This promise cannot be rejected. It's either infinitely + * pending or resolved with whichever Response was passed to `respondWith()`. + */ + [kResponsePromise]: DeferredPromise; + + /** + * Internal flag indicating if this request has been handled. + * @note The response promise becomes "fulfilled" on the next tick. + */ + [kRequestHandled]: boolean + + constructor(private request: Request) { + this[kRequestHandled] = false + this[kResponsePromise] = new DeferredPromise() + } + + /** + * Respond to this request with the given `Response` instance. + * @example + * controller.respondWith(new Response()) + * controller.respondWith(Response.json({ id })) + * controller.respondWith(Response.error()) + */ + public respondWith(response: Response): void { + invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to respond to the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ) + + this[kRequestHandled] = true + this[kResponsePromise].resolve(response) + + /** + * @note The request conrtoller doesn't do anything + * apart from letting the interceptor await the response + * provided by the developer through the response promise. + * Each interceptor implements the actual respondWith/errorWith + * logic based on that interceptor's needs. + */ + } + + /** + * Error this request with the given error. + * @example + * controller.errorWith() + * controller.errorWith(new Error('Oops!')) + */ + public errorWith(error?: Error): void { + invariant.as( + InterceptorError, + !this[kRequestHandled], + 'Failed to error the "%s %s" request: the "request" event has already been handled.', + this.request.method, + this.request.url + ) + + this[kRequestHandled] = true + + /** + * @note Resolve the response promise, not reject. + * This helps us differentiate between unhandled exceptions + * and intended errors ("errorWith") while waiting for the response. + */ + this[kResponsePromise].resolve(error) + } +} diff --git a/node_modules/@mswjs/interceptors/src/createRequestId.test.ts b/node_modules/@mswjs/interceptors/src/createRequestId.test.ts new file mode 100644 index 0000000000..a59b2c049f --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/createRequestId.test.ts @@ -0,0 +1,7 @@ +import { it, expect } from 'vitest' +import { createRequestId } from './createRequestId' +import { REQUEST_ID_REGEXP } from '../test/helpers' + +it('returns a request ID', () => { + expect(createRequestId()).toMatch(REQUEST_ID_REGEXP) +}) diff --git a/node_modules/@mswjs/interceptors/src/createRequestId.ts b/node_modules/@mswjs/interceptors/src/createRequestId.ts new file mode 100644 index 0000000000..318d2eb954 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/createRequestId.ts @@ -0,0 +1,9 @@ +/** + * Generate a random ID string to represent a request. + * @example + * createRequestId() + * // "f774b6c9c600f" + */ +export function createRequestId(): string { + return Math.random().toString(16).slice(2) +} diff --git a/node_modules/@mswjs/interceptors/src/glossary.ts b/node_modules/@mswjs/interceptors/src/glossary.ts new file mode 100644 index 0000000000..2015852701 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/glossary.ts @@ -0,0 +1,37 @@ +import type { RequestController } from './RequestController' + +export const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule') + +/** + * @note Export `RequestController` as a type only. + * It's never meant to be created in the userland. + */ +export type { RequestController } + +export type RequestCredentials = 'omit' | 'include' | 'same-origin' + +export type HttpRequestEventMap = { + request: [ + args: { + request: Request + requestId: string + controller: RequestController + } + ] + response: [ + args: { + response: Response + isMockedResponse: boolean + request: Request + requestId: string + } + ] + unhandledException: [ + args: { + error: unknown + request: Request + requestId: string + controller: RequestController + } + ] +} diff --git a/node_modules/@mswjs/interceptors/src/index.ts b/node_modules/@mswjs/interceptors/src/index.ts new file mode 100644 index 0000000000..21aa732be8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/index.ts @@ -0,0 +1,9 @@ +export * from './glossary' +export * from './Interceptor' +export * from './BatchInterceptor' + +/* Utils */ +export { createRequestId } from './createRequestId' +export { getCleanUrl } from './utils/getCleanUrl' +export { encodeBuffer, decodeBuffer } from './utils/bufferUtils' +export { FetchResponse } from './utils/fetchUtils' diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/MockHttpSocket.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/MockHttpSocket.ts new file mode 100644 index 0000000000..45cf6b5dd2 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/MockHttpSocket.ts @@ -0,0 +1,628 @@ +import net from 'node:net' +import { + HTTPParser, + type RequestHeadersCompleteCallback, + type ResponseHeadersCompleteCallback, +} from '_http_common' +import { STATUS_CODES, IncomingMessage, ServerResponse } from 'node:http' +import { Readable } from 'node:stream' +import { invariant } from 'outvariant' +import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor' +import { MockSocket } from '../Socket/MockSocket' +import type { NormalizedSocketWriteArgs } from '../Socket/utils/normalizeSocketWriteArgs' +import { isPropertyAccessible } from '../../utils/isPropertyAccessible' +import { baseUrlFromConnectionOptions } from '../Socket/utils/baseUrlFromConnectionOptions' +import { createServerErrorResponse } from '../../utils/responseUtils' +import { createRequestId } from '../../createRequestId' +import { getRawFetchHeaders } from './utils/recordRawHeaders' +import { FetchResponse } from '../../utils/fetchUtils' + +type HttpConnectionOptions = any + +export type MockHttpSocketRequestCallback = (args: { + requestId: string + request: Request + socket: MockHttpSocket +}) => void + +export type MockHttpSocketResponseCallback = (args: { + requestId: string + request: Request + response: Response + isMockedResponse: boolean + socket: MockHttpSocket +}) => Promise + +interface MockHttpSocketOptions { + connectionOptions: HttpConnectionOptions + createConnection: () => net.Socket + onRequest: MockHttpSocketRequestCallback + onResponse: MockHttpSocketResponseCallback +} + +export const kRequestId = Symbol('kRequestId') + +export class MockHttpSocket extends MockSocket { + private connectionOptions: HttpConnectionOptions + private createConnection: () => net.Socket + private baseUrl: URL + + private onRequest: MockHttpSocketRequestCallback + private onResponse: MockHttpSocketResponseCallback + private responseListenersPromise?: Promise + + private writeBuffer: Array = [] + private request?: Request + private requestParser: HTTPParser<0> + private requestStream?: Readable + private shouldKeepAlive?: boolean + + private socketState: 'unknown' | 'mock' | 'passthrough' = 'unknown' + private responseParser: HTTPParser<1> + private responseStream?: Readable + private originalSocket?: net.Socket + + constructor(options: MockHttpSocketOptions) { + super({ + write: (chunk, encoding, callback) => { + // Buffer the writes so they can be flushed in case of the original connection + // and when reading the request body in the interceptor. If the connection has + // been established, no need to buffer the chunks anymore, they will be forwarded. + if (this.socketState !== 'passthrough') { + this.writeBuffer.push([chunk, encoding, callback]) + } + + if (chunk) { + /** + * Forward any writes to the mock socket to the underlying original socket. + * This ensures functional duplex connections, like WebSocket. + * @see https://github.com/mswjs/interceptors/issues/682 + */ + if (this.socketState === 'passthrough') { + this.originalSocket?.write(chunk, encoding, callback) + } + + this.requestParser.execute( + Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding) + ) + } + }, + read: (chunk) => { + if (chunk !== null) { + /** + * @todo We need to free the parser if the connection has been + * upgraded to a non-HTTP protocol. It won't be able to parse data + * from that point onward anyway. No need to keep it in memory. + */ + this.responseParser.execute( + Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk) + ) + } + }, + }) + + this.connectionOptions = options.connectionOptions + this.createConnection = options.createConnection + this.onRequest = options.onRequest + this.onResponse = options.onResponse + + this.baseUrl = baseUrlFromConnectionOptions(this.connectionOptions) + + // Request parser. + this.requestParser = new HTTPParser() + this.requestParser.initialize(HTTPParser.REQUEST, {}) + this.requestParser[HTTPParser.kOnHeadersComplete] = + this.onRequestStart.bind(this) + this.requestParser[HTTPParser.kOnBody] = this.onRequestBody.bind(this) + this.requestParser[HTTPParser.kOnMessageComplete] = + this.onRequestEnd.bind(this) + + // Response parser. + this.responseParser = new HTTPParser() + this.responseParser.initialize(HTTPParser.RESPONSE, {}) + this.responseParser[HTTPParser.kOnHeadersComplete] = + this.onResponseStart.bind(this) + this.responseParser[HTTPParser.kOnBody] = this.onResponseBody.bind(this) + this.responseParser[HTTPParser.kOnMessageComplete] = + this.onResponseEnd.bind(this) + + // Once the socket is finished, nothing can write to it + // anymore. It has also flushed any buffered chunks. + this.once('finish', () => this.requestParser.free()) + + if (this.baseUrl.protocol === 'https:') { + Reflect.set(this, 'encrypted', true) + // The server certificate is not the same as a CA + // passed to the TLS socket connection options. + Reflect.set(this, 'authorized', false) + Reflect.set(this, 'getProtocol', () => 'TLSv1.3') + Reflect.set(this, 'getSession', () => undefined) + Reflect.set(this, 'isSessionReused', () => false) + } + } + + public emit(event: string | symbol, ...args: any[]): boolean { + const emitEvent = super.emit.bind(this, event as any, ...args) + + if (this.responseListenersPromise) { + this.responseListenersPromise.finally(emitEvent) + return this.listenerCount(event) > 0 + } + + return emitEvent() + } + + public destroy(error?: Error | undefined): this { + // Destroy the response parser when the socket gets destroyed. + // Normally, we shoud listen to the "close" event but it + // can be suppressed by using the "emitClose: false" option. + this.responseParser.free() + + if (error) { + this.emit('error', error) + } + + return super.destroy(error) + } + + /** + * Establish this Socket connection as-is and pipe + * its data/events through this Socket. + */ + public passthrough(): void { + this.socketState = 'passthrough' + + if (this.destroyed) { + return + } + + const socket = this.createConnection() + this.originalSocket = socket + + // If the developer destroys the socket, destroy the original connection. + this.once('error', (error) => { + socket.destroy(error) + }) + + this.address = socket.address.bind(socket) + + // Flush the buffered "socket.write()" calls onto + // the original socket instance (i.e. write request body). + // Exhaust the "requestBuffer" in case this Socket + // gets reused for different requests. + let writeArgs: NormalizedSocketWriteArgs | undefined + let headersWritten = false + + while ((writeArgs = this.writeBuffer.shift())) { + if (writeArgs !== undefined) { + if (!headersWritten) { + const [chunk, encoding, callback] = writeArgs + const chunkString = chunk.toString() + const chunkBeforeRequestHeaders = chunkString.slice( + 0, + chunkString.indexOf('\r\n') + 2 + ) + const chunkAfterRequestHeaders = chunkString.slice( + chunk.indexOf('\r\n\r\n') + ) + const rawRequestHeaders = getRawFetchHeaders(this.request!.headers) + const requestHeadersString = rawRequestHeaders + // Skip the internal request ID deduplication header. + .filter(([name]) => { + return name.toLowerCase() !== INTERNAL_REQUEST_ID_HEADER_NAME + }) + .map(([name, value]) => `${name}: ${value}`) + .join('\r\n') + + // Modify the HTTP request message headers + // to reflect any changes to the request headers + // from the "request" event listener. + const headersChunk = `${chunkBeforeRequestHeaders}${requestHeadersString}${chunkAfterRequestHeaders}` + socket.write(headersChunk, encoding, callback) + headersWritten = true + continue + } + + socket.write(...writeArgs) + } + } + + // Forward TLS Socket properties onto this Socket instance + // in the case of a TLS/SSL connection. + if (Reflect.get(socket, 'encrypted')) { + const tlsProperties = [ + 'encrypted', + 'authorized', + 'getProtocol', + 'getSession', + 'isSessionReused', + ] + + tlsProperties.forEach((propertyName) => { + Object.defineProperty(this, propertyName, { + enumerable: true, + get: () => { + const value = Reflect.get(socket, propertyName) + return typeof value === 'function' ? value.bind(socket) : value + }, + }) + }) + } + + socket + .on('lookup', (...args) => this.emit('lookup', ...args)) + .on('connect', () => { + this.connecting = socket.connecting + this.emit('connect') + }) + .on('secureConnect', () => this.emit('secureConnect')) + .on('secure', () => this.emit('secure')) + .on('session', (session) => this.emit('session', session)) + .on('ready', () => this.emit('ready')) + .on('drain', () => this.emit('drain')) + .on('data', (chunk) => { + // Push the original response to this socket + // so it triggers the HTTP response parser. This unifies + // the handling pipeline for original and mocked response. + this.push(chunk) + }) + .on('error', (error) => { + Reflect.set(this, '_hadError', Reflect.get(socket, '_hadError')) + this.emit('error', error) + }) + .on('resume', () => this.emit('resume')) + .on('timeout', () => this.emit('timeout')) + .on('prefinish', () => this.emit('prefinish')) + .on('finish', () => this.emit('finish')) + .on('close', (hadError) => this.emit('close', hadError)) + .on('end', () => this.emit('end')) + } + + /** + * Convert the given Fetch API `Response` instance to an + * HTTP message and push it to the socket. + */ + public async respondWith(response: Response): Promise { + // Ignore the mocked response if the socket has been destroyed + // (e.g. aborted or timed out), + if (this.destroyed) { + return + } + + // Handle "type: error" responses. + if (isPropertyAccessible(response, 'type') && response.type === 'error') { + this.errorWith(new TypeError('Network error')) + return + } + + // First, emit all the connection events + // to emulate a successful connection. + this.mockConnect() + this.socketState = 'mock' + + // Flush the write buffer to trigger write callbacks + // if it hasn't been flushed already (e.g. someone started reading request stream). + this.flushWriteBuffer() + + // Create a `ServerResponse` instance to delegate HTTP message parsing, + // Transfer-Encoding, and other things to Node.js internals. + const serverResponse = new ServerResponse(new IncomingMessage(this)) + + /** + * Assign a mock socket instance to the server response to + * spy on the response chunk writes. Push the transformed response chunks + * to this `MockHttpSocket` instance to trigger the "data" event. + * @note Providing the same `MockSocket` instance when creating `ServerResponse` + * does not have the same effect. + * @see https://github.com/nodejs/node/blob/10099bb3f7fd97bb9dd9667188426866b3098e07/test/parallel/test-http-server-response-standalone.js#L32 + */ + serverResponse.assignSocket( + new MockSocket({ + write: (chunk, encoding, callback) => { + this.push(chunk, encoding) + callback?.() + }, + read() {}, + }) + ) + + /** + * @note Remove the `Connection` and `Date` response headers + * injected by `ServerResponse` by default. Those are required + * from the server but the interceptor is NOT technically a server. + * It's confusing to add response headers that the developer didn't + * specify themselves. They can always add these if they wish. + * @see https://www.rfc-editor.org/rfc/rfc9110#field.date + * @see https://www.rfc-editor.org/rfc/rfc9110#field.connection + */ + serverResponse.removeHeader('connection') + serverResponse.removeHeader('date') + + const rawResponseHeaders = getRawFetchHeaders(response.headers) + + /** + * @note Call `.writeHead` in order to set the raw response headers + * in the same case as they were provided by the developer. Using + * `.setHeader()`/`.appendHeader()` normalizes header names. + */ + serverResponse.writeHead( + response.status, + response.statusText || STATUS_CODES[response.status], + rawResponseHeaders + ) + + // If the developer destroy the socket, gracefully destroy the response. + this.once('error', () => { + serverResponse.destroy() + }) + + if (response.body) { + try { + const reader = response.body.getReader() + + while (true) { + const { done, value } = await reader.read() + + if (done) { + serverResponse.end() + break + } + + serverResponse.write(value) + } + } catch (error) { + // Coerce response stream errors to 500 responses. + this.respondWith(createServerErrorResponse(error)) + return + } + } else { + serverResponse.end() + } + + // Close the socket if the connection wasn't marked as keep-alive. + if (!this.shouldKeepAlive) { + this.emit('readable') + + /** + * @todo @fixme This is likely a hack. + * Since we push null to the socket, it never propagates to the + * parser, and the parser never calls "onResponseEnd" to close + * the response stream. We are closing the stream here manually + * but that shouldn't be the case. + */ + this.responseStream?.push(null) + this.push(null) + } + } + + /** + * Close this socket connection with the given error. + */ + public errorWith(error?: Error): void { + this.destroy(error) + } + + private mockConnect(): void { + // Calling this method immediately puts the socket + // into the connected state. + this.connecting = false + + const isIPv6 = + net.isIPv6(this.connectionOptions.hostname) || + this.connectionOptions.family === 6 + const addressInfo = { + address: isIPv6 ? '::1' : '127.0.0.1', + family: isIPv6 ? 'IPv6' : 'IPv4', + port: this.connectionOptions.port, + } + // Return fake address information for the socket. + this.address = () => addressInfo + this.emit( + 'lookup', + null, + addressInfo.address, + addressInfo.family === 'IPv6' ? 6 : 4, + this.connectionOptions.host + ) + this.emit('connect') + this.emit('ready') + + if (this.baseUrl.protocol === 'https:') { + this.emit('secure') + this.emit('secureConnect') + + // A single TLS connection is represented by two "session" events. + this.emit( + 'session', + this.connectionOptions.session || + Buffer.from('mock-session-renegotiate') + ) + this.emit('session', Buffer.from('mock-session-resume')) + } + } + + private flushWriteBuffer(): void { + for (const writeCall of this.writeBuffer) { + if (typeof writeCall[2] === 'function') { + writeCall[2]() + /** + * @note Remove the callback from the write call + * so it doesn't get called twice on passthrough + * if `request.end()` was called within `request.write()`. + * @see https://github.com/mswjs/interceptors/issues/684 + */ + writeCall[2] = undefined + } + } + } + + private onRequestStart: RequestHeadersCompleteCallback = ( + versionMajor, + versionMinor, + rawHeaders, + _, + path, + __, + ___, + ____, + shouldKeepAlive + ) => { + this.shouldKeepAlive = shouldKeepAlive + + const url = new URL(path, this.baseUrl) + const method = this.connectionOptions.method?.toUpperCase() || 'GET' + const headers = FetchResponse.parseRawHeaders(rawHeaders) + const canHaveBody = method !== 'GET' && method !== 'HEAD' + + // Translate the basic authorization in the URL to the request header. + // Constructing a Request instance with a URL containing auth is no-op. + if (url.username || url.password) { + if (!headers.has('authorization')) { + headers.set('authorization', `Basic ${url.username}:${url.password}`) + } + url.username = '' + url.password = '' + } + + // Create a new stream for each request. + // If this Socket is reused for multiple requests, + // this ensures that each request gets its own stream. + // One Socket instance can only handle one request at a time. + if (canHaveBody) { + this.requestStream = new Readable({ + /** + * @note Provide the `read()` method so a `Readable` could be + * used as the actual request body (the stream calls "read()"). + * We control the queue in the onRequestBody/End functions. + */ + read: () => { + // If the user attempts to read the request body, + // flush the write buffer to trigger the callbacks. + // This way, if the request stream ends in the write callback, + // it will indeed end correctly. + this.flushWriteBuffer() + }, + }) + } + + const requestId = createRequestId() + this.request = new Request(url, { + method, + headers, + credentials: 'same-origin', + // @ts-expect-error Undocumented Fetch property. + duplex: canHaveBody ? 'half' : undefined, + body: canHaveBody ? (Readable.toWeb(this.requestStream!) as any) : null, + }) + + Reflect.set(this.request, kRequestId, requestId) + + // Skip handling the request that's already being handled + // by another (parent) interceptor. For example, XMLHttpRequest + // is often implemented via ClientRequest in Node.js (e.g. JSDOM). + // In that case, XHR interceptor will bubble down to the ClientRequest + // interceptor. No need to try to handle that request again. + /** + * @fixme Stop relying on the "X-Request-Id" request header + * to figure out if one interceptor has been invoked within another. + * @see https://github.com/mswjs/interceptors/issues/378 + */ + if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) { + this.passthrough() + return + } + + this.onRequest({ + requestId, + request: this.request, + socket: this, + }) + } + + private onRequestBody(chunk: Buffer): void { + invariant( + this.requestStream, + 'Failed to write to a request stream: stream does not exist' + ) + + this.requestStream.push(chunk) + } + + private onRequestEnd(): void { + // Request end can be called for requests without body. + if (this.requestStream) { + this.requestStream.push(null) + } + } + + private onResponseStart: ResponseHeadersCompleteCallback = ( + versionMajor, + versionMinor, + rawHeaders, + method, + url, + status, + statusText + ) => { + const headers = FetchResponse.parseRawHeaders(rawHeaders) + + const response = new FetchResponse( + /** + * @note The Fetch API response instance exposed to the consumer + * is created over the response stream of the HTTP parser. It is NOT + * related to the Socket instance. This way, you can read response body + * in response listener while the Socket instance delays the emission + * of "end" and other events until those response listeners are finished. + */ + FetchResponse.isResponseWithBody(status) + ? (Readable.toWeb( + (this.responseStream = new Readable({ read() {} })) + ) as any) + : null, + { + url, + status, + statusText, + headers, + } + ) + + invariant( + this.request, + 'Failed to handle a response: request does not exist' + ) + + /** + * @fixme Stop relying on the "X-Request-Id" request header + * to figure out if one interceptor has been invoked within another. + * @see https://github.com/mswjs/interceptors/issues/378 + */ + if (this.request.headers.has(INTERNAL_REQUEST_ID_HEADER_NAME)) { + return + } + + this.responseListenersPromise = this.onResponse({ + response, + isMockedResponse: this.socketState === 'mock', + requestId: Reflect.get(this.request, kRequestId), + request: this.request, + socket: this, + }) + } + + private onResponseBody(chunk: Buffer) { + invariant( + this.responseStream, + 'Failed to write to a response stream: stream does not exist' + ) + + this.responseStream.push(chunk) + } + + private onResponseEnd(): void { + // Response end can be called for responses without body. + if (this.responseStream) { + this.responseStream.push(null) + } + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/agents.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/agents.ts new file mode 100644 index 0000000000..e5f95a8259 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/agents.ts @@ -0,0 +1,86 @@ +import net from 'node:net' +import http from 'node:http' +import https from 'node:https' +import { + MockHttpSocket, + type MockHttpSocketRequestCallback, + type MockHttpSocketResponseCallback, +} from './MockHttpSocket' + +declare module 'node:http' { + interface Agent { + createConnection(options: any, callback: any): net.Socket + } +} + +interface MockAgentOptions { + customAgent?: http.RequestOptions['agent'] + onRequest: MockHttpSocketRequestCallback + onResponse: MockHttpSocketResponseCallback +} + +export class MockAgent extends http.Agent { + private customAgent?: http.RequestOptions['agent'] + private onRequest: MockHttpSocketRequestCallback + private onResponse: MockHttpSocketResponseCallback + + constructor(options: MockAgentOptions) { + super() + this.customAgent = options.customAgent + this.onRequest = options.onRequest + this.onResponse = options.onResponse + } + + public createConnection(options: any, callback: any): net.Socket { + const createConnection = + (this.customAgent instanceof http.Agent && + this.customAgent.createConnection) || + super.createConnection + + const socket = new MockHttpSocket({ + connectionOptions: options, + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), + onRequest: this.onRequest.bind(this), + onResponse: this.onResponse.bind(this), + }) + + return socket + } +} + +export class MockHttpsAgent extends https.Agent { + private customAgent?: https.RequestOptions['agent'] + private onRequest: MockHttpSocketRequestCallback + private onResponse: MockHttpSocketResponseCallback + + constructor(options: MockAgentOptions) { + super() + this.customAgent = options.customAgent + this.onRequest = options.onRequest + this.onResponse = options.onResponse + } + + public createConnection(options: any, callback: any): net.Socket { + const createConnection = + (this.customAgent instanceof https.Agent && + this.customAgent.createConnection) || + super.createConnection + + const socket = new MockHttpSocket({ + connectionOptions: options, + createConnection: createConnection.bind( + this.customAgent || this, + options, + callback + ), + onRequest: this.onRequest.bind(this), + onResponse: this.onResponse.bind(this), + }) + + return socket + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/index.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/index.test.ts new file mode 100644 index 0000000000..98539017d0 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/index.test.ts @@ -0,0 +1,75 @@ +import { it, expect, beforeAll, afterEach, afterAll } from 'vitest' +import http from 'node:http' +import { HttpServer } from '@open-draft/test-server/http' +import { DeferredPromise } from '@open-draft/deferred-promise' +import { ClientRequestInterceptor } from '.' +import { sleep, waitForClientRequest } from '../../../test/helpers' + +const httpServer = new HttpServer((app) => { + app.get('/', (_req, res) => { + res.status(200).send('/') + }) + app.get('/get', (_req, res) => { + res.status(200).send('/get') + }) +}) + +const interceptor = new ClientRequestInterceptor() + +beforeAll(async () => { + interceptor.apply() + await httpServer.listen() +}) + +afterEach(() => { + interceptor.removeAllListeners() +}) + +afterAll(async () => { + interceptor.dispose() + await httpServer.close() +}) + +it('abort the request if the abort signal is emitted', async () => { + const requestUrl = httpServer.http.url('/') + + interceptor.on('request', async function delayedResponse({ controller }) { + await sleep(1_000) + controller.respondWith(new Response()) + }) + + const abortController = new AbortController() + const request = http.get(requestUrl, { signal: abortController.signal }) + + abortController.abort() + + const abortErrorPromise = new DeferredPromise() + request.on('error', function (error) { + abortErrorPromise.resolve(error) + }) + + const abortError = await abortErrorPromise + expect(abortError.name).toEqual('AbortError') + + expect(request.destroyed).toBe(true) +}) + +it('patch the Headers object correctly after dispose and reapply', async () => { + interceptor.dispose() + interceptor.apply() + + interceptor.on('request', ({ controller }) => { + const headers = new Headers({ + 'X-CustoM-HeadeR': 'Yes', + }) + controller.respondWith(new Response(null, { headers })) + }) + + const request = http.get(httpServer.http.url('/')) + const { res } = await waitForClientRequest(request) + + expect(res.rawHeaders).toEqual( + expect.arrayContaining(['X-CustoM-HeadeR', 'Yes']) + ) + expect(res.headers['x-custom-header']).toEqual('Yes') +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/index.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/index.ts new file mode 100644 index 0000000000..c5dac7a33e --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/index.ts @@ -0,0 +1,170 @@ +import http from 'node:http' +import https from 'node:https' +import { Interceptor } from '../../Interceptor' +import type { HttpRequestEventMap } from '../../glossary' +import { + kRequestId, + MockHttpSocketRequestCallback, + MockHttpSocketResponseCallback, +} from './MockHttpSocket' +import { MockAgent, MockHttpsAgent } from './agents' +import { RequestController } from '../../RequestController' +import { emitAsync } from '../../utils/emitAsync' +import { normalizeClientRequestArgs } from './utils/normalizeClientRequestArgs' +import { handleRequest } from '../../utils/handleRequest' +import { + recordRawFetchHeaders, + restoreHeadersPrototype, +} from './utils/recordRawHeaders' + +export class ClientRequestInterceptor extends Interceptor { + static symbol = Symbol('client-request-interceptor') + + constructor() { + super(ClientRequestInterceptor.symbol) + } + + protected setup(): void { + const { get: originalGet, request: originalRequest } = http + const { get: originalHttpsGet, request: originalHttpsRequest } = https + + const onRequest = this.onRequest.bind(this) + const onResponse = this.onResponse.bind(this) + + http.request = new Proxy(http.request, { + apply: (target, thisArg, args: Parameters) => { + const [url, options, callback] = normalizeClientRequestArgs( + 'http:', + args + ) + const mockAgent = new MockAgent({ + customAgent: options.agent, + onRequest, + onResponse, + }) + options.agent = mockAgent + + return Reflect.apply(target, thisArg, [url, options, callback]) + }, + }) + + http.get = new Proxy(http.get, { + apply: (target, thisArg, args: Parameters) => { + const [url, options, callback] = normalizeClientRequestArgs( + 'http:', + args + ) + + const mockAgent = new MockAgent({ + customAgent: options.agent, + onRequest, + onResponse, + }) + options.agent = mockAgent + + return Reflect.apply(target, thisArg, [url, options, callback]) + }, + }) + + // + // HTTPS. + // + + https.request = new Proxy(https.request, { + apply: (target, thisArg, args: Parameters) => { + const [url, options, callback] = normalizeClientRequestArgs( + 'https:', + args + ) + + const mockAgent = new MockHttpsAgent({ + customAgent: options.agent, + onRequest, + onResponse, + }) + options.agent = mockAgent + + return Reflect.apply(target, thisArg, [url, options, callback]) + }, + }) + + https.get = new Proxy(https.get, { + apply: (target, thisArg, args: Parameters) => { + const [url, options, callback] = normalizeClientRequestArgs( + 'https:', + args + ) + + const mockAgent = new MockHttpsAgent({ + customAgent: options.agent, + onRequest, + onResponse, + }) + options.agent = mockAgent + + return Reflect.apply(target, thisArg, [url, options, callback]) + }, + }) + + // Spy on `Header.prototype.set` and `Header.prototype.append` calls + // and record the raw header names provided. This is to support + // `IncomingMessage.prototype.rawHeaders`. + recordRawFetchHeaders() + + this.subscriptions.push(() => { + http.get = originalGet + http.request = originalRequest + + https.get = originalHttpsGet + https.request = originalHttpsRequest + + restoreHeadersPrototype() + }) + } + + private onRequest: MockHttpSocketRequestCallback = async ({ + request, + socket, + }) => { + const requestId = Reflect.get(request, kRequestId) + const controller = new RequestController(request) + + const isRequestHandled = await handleRequest({ + request, + requestId, + controller, + emitter: this.emitter, + onResponse: (response) => { + socket.respondWith(response) + }, + onRequestError: (response) => { + socket.respondWith(response) + }, + onError: (error) => { + if (error instanceof Error) { + socket.errorWith(error) + } + }, + }) + + if (!isRequestHandled) { + return socket.passthrough() + } + } + + public onResponse: MockHttpSocketResponseCallback = async ({ + requestId, + request, + response, + isMockedResponse, + }) => { + // Return the promise to when all the response event listeners + // are finished. + return emitAsync(this.emitter, 'response', { + requestId, + request, + response, + isMockedResponse, + }) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts new file mode 100644 index 0000000000..314120c326 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts @@ -0,0 +1,54 @@ +import { it, expect } from 'vitest' +import { IncomingMessage } from 'http' +import { Socket } from 'net' +import * as zlib from 'zlib' +import { getIncomingMessageBody } from './getIncomingMessageBody' + +it('returns utf8 string given a utf8 response body', async () => { + const utfBuffer = Buffer.from('one') + const message = new IncomingMessage(new Socket()) + + const pendingResponseBody = getIncomingMessageBody(message) + message.emit('data', utfBuffer) + message.emit('end') + + expect(await pendingResponseBody).toEqual('one') +}) + +it('returns utf8 string given a gzipped response body', async () => { + const utfBuffer = zlib.gzipSync(Buffer.from('two')) + const message = new IncomingMessage(new Socket()) + message.headers = { + 'content-encoding': 'gzip', + } + + const pendingResponseBody = getIncomingMessageBody(message) + message.emit('data', utfBuffer) + message.emit('end') + + expect(await pendingResponseBody).toEqual('two') +}) + +it('returns utf8 string given a gzipped response body with incorrect "content-lenght"', async () => { + const utfBuffer = zlib.gzipSync(Buffer.from('three')) + const message = new IncomingMessage(new Socket()) + message.headers = { + 'content-encoding': 'gzip', + 'content-length': '500', + } + + const pendingResponseBody = getIncomingMessageBody(message) + message.emit('data', utfBuffer) + message.emit('end') + + expect(await pendingResponseBody).toEqual('three') +}) + +it('returns empty string given an empty body', async () => { + const message = new IncomingMessage(new Socket()) + + const pendingResponseBody = getIncomingMessageBody(message) + message.emit('end') + + expect(await pendingResponseBody).toEqual('') +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts new file mode 100644 index 0000000000..563e552597 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts @@ -0,0 +1,45 @@ +import { IncomingMessage } from 'http' +import { PassThrough } from 'stream' +import * as zlib from 'zlib' +import { Logger } from '@open-draft/logger' + +const logger = new Logger('http getIncomingMessageBody') + +export function getIncomingMessageBody( + response: IncomingMessage +): Promise { + return new Promise((resolve, reject) => { + logger.info('cloning the original response...') + + // Pipe the original response to support non-clone + // "response" input. No need to clone the response, + // as we always have access to the full "response" input, + // either a clone or an original one (in tests). + const responseClone = response.pipe(new PassThrough()) + const stream = + response.headers['content-encoding'] === 'gzip' + ? responseClone.pipe(zlib.createGunzip()) + : responseClone + + const encoding = response.readableEncoding || 'utf8' + stream.setEncoding(encoding) + logger.info('using encoding:', encoding) + + let body = '' + + stream.on('data', (responseBody) => { + logger.info('response body read:', responseBody) + body += responseBody + }) + + stream.once('end', () => { + logger.info('response body end') + resolve(body) + }) + + stream.once('error', (error) => { + logger.info('error while reading response body:', error) + reject(error) + }) + }) +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts new file mode 100644 index 0000000000..3eb551fdb0 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts @@ -0,0 +1,447 @@ +import { it, expect } from 'vitest' +import { parse } from 'url' +import { globalAgent as httpGlobalAgent, RequestOptions } from 'http' +import { Agent as HttpsAgent, globalAgent as httpsGlobalAgent } from 'https' +import { getUrlByRequestOptions } from '../../../utils/getUrlByRequestOptions' +import { normalizeClientRequestArgs } from './normalizeClientRequestArgs' + +it('handles [string, callback] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('https:', [ + 'https://mswjs.io/resource', + function cb() {}, + ]) + + // URL string must be converted to a URL instance. + expect(url.href).toEqual('https://mswjs.io/resource') + + // Request options must be derived from the URL instance. + expect(options).toHaveProperty('method', 'GET') + expect(options).toHaveProperty('protocol', 'https:') + expect(options).toHaveProperty('hostname', 'mswjs.io') + expect(options).toHaveProperty('path', '/resource') + + // Callback must be preserved. + expect(callback?.name).toEqual('cb') +}) + +it('handles [string, RequestOptions, callback] input', () => { + const initialOptions = { + headers: { + 'Content-Type': 'text/plain', + }, + } + const [url, options, callback] = normalizeClientRequestArgs('https:', [ + 'https://mswjs.io/resource', + initialOptions, + function cb() {}, + ]) + + // URL must be created from the string. + expect(url.href).toEqual('https://mswjs.io/resource') + + // Request options must be preserved. + expect(options).toHaveProperty('headers', initialOptions.headers) + + // Callback must be preserved. + expect(callback?.name).toEqual('cb') +}) + +it('handles [URL, callback] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('https:', [ + new URL('https://mswjs.io/resource'), + function cb() {}, + ]) + + // URL must be preserved. + expect(url.href).toEqual('https://mswjs.io/resource') + + // Request options must be derived from the URL instance. + expect(options.method).toEqual('GET') + expect(options.protocol).toEqual('https:') + expect(options.hostname).toEqual('mswjs.io') + expect(options.path).toEqual('/resource') + + // Callback must be preserved. + expect(callback?.name).toEqual('cb') +}) + +it('handles [Absolute Legacy URL, callback] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('https:', [ + parse('https://cherry:durian@mswjs.io:12345/resource?apple=banana'), + function cb() {}, + ]) + + // URL must be preserved. + expect(url.toJSON()).toEqual( + new URL( + 'https://cherry:durian@mswjs.io:12345/resource?apple=banana' + ).toJSON() + ) + + // Request options must be derived from the URL instance. + expect(options.method).toEqual('GET') + expect(options.protocol).toEqual('https:') + expect(options.hostname).toEqual('mswjs.io') + expect(options.path).toEqual('/resource?apple=banana') + expect(options.port).toEqual(12345) + expect(options.auth).toEqual('cherry:durian') + + // Callback must be preserved. + expect(callback?.name).toEqual('cb') +}) + +it('handles [Relative Legacy URL, RequestOptions without path set, callback] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('http:', [ + parse('/resource?apple=banana'), + { host: 'mswjs.io' }, + function cb() {}, + ]) + + // Correct WHATWG URL generated. + expect(url.toJSON()).toEqual( + new URL('http://mswjs.io/resource?apple=banana').toJSON() + ) + + // No path in request options, so legacy url path is copied-in. + expect(options.protocol).toEqual('http:') + expect(options.host).toEqual('mswjs.io') + expect(options.path).toEqual('/resource?apple=banana') + + // Callback must be preserved. + expect(callback?.name).toEqual('cb') +}) + +it('handles [Relative Legacy URL, RequestOptions with path set, callback] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('http:', [ + parse('/resource?apple=banana'), + { host: 'mswjs.io', path: '/other?cherry=durian' }, + function cb() {}, + ]) + + // Correct WHATWG URL generated. + expect(url.toJSON()).toEqual( + new URL('http://mswjs.io/other?cherry=durian').toJSON() + ) + + // Path in request options, so that path is preferred. + expect(options.protocol).toEqual('http:') + expect(options.host).toEqual('mswjs.io') + expect(options.path).toEqual('/other?cherry=durian') + + // Callback must be preserved. + expect(callback?.name).toEqual('cb') +}) + +it('handles [Relative Legacy URL, callback] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('http:', [ + parse('/resource?apple=banana'), + function cb() {}, + ]) + + // Correct WHATWG URL generated. + expect(url.toJSON()).toMatch( + getUrlByRequestOptions({ path: '/resource?apple=banana' }).toJSON() + ) + + // Check path is in options. + expect(options.protocol).toEqual('http:') + expect(options.path).toEqual('/resource?apple=banana') + + // Callback must be preserved. + expect(callback).toBeTypeOf('function') + expect(callback?.name).toEqual('cb') +}) + +it('handles [Relative Legacy URL] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('http:', [ + parse('/resource?apple=banana'), + ]) + + // Correct WHATWG URL generated. + expect(url.toJSON()).toMatch( + getUrlByRequestOptions({ path: '/resource?apple=banana' }).toJSON() + ) + + // Check path is in options. + expect(options.protocol).toEqual('http:') + expect(options.path).toEqual('/resource?apple=banana') + + // Callback must be preserved. + expect(callback).toBeUndefined() +}) + +it('handles [URL, RequestOptions, callback] input', () => { + const [url, options, callback] = normalizeClientRequestArgs('https:', [ + new URL('https://mswjs.io/resource'), + { + agent: false, + headers: { + 'Content-Type': 'text/plain', + }, + }, + function cb() {}, + ]) + + // URL must be preserved. + expect(url.href).toEqual('https://mswjs.io/resource') + + // Options must be preserved. + // `urlToHttpOptions` from `node:url` generates additional + // ClientRequest options, some of which are not legally allowed. + expect(options).toMatchObject({ + agent: false, + _defaultAgent: httpsGlobalAgent, + protocol: url.protocol, + method: 'GET', + headers: { + 'Content-Type': 'text/plain', + }, + hostname: url.hostname, + path: url.pathname, + }) + + // Callback must be preserved. + expect(callback).toBeTypeOf('function') + expect(callback?.name).toEqual('cb') +}) + +it('handles [URL, RequestOptions] where options have custom "hostname"', () => { + const [url, options] = normalizeClientRequestArgs('http:', [ + new URL('http://example.com/path-from-url'), + { + hostname: 'host-from-options.com', + }, + ]) + expect(url.href).toBe('http://host-from-options.com/path-from-url') + expect(options).toMatchObject({ + hostname: 'host-from-options.com', + path: '/path-from-url', + }) +}) + +it('handles [URL, RequestOptions] where options contain "host" and "path" and "port"', () => { + const [url, options] = normalizeClientRequestArgs('http:', [ + new URL('http://example.com/path-from-url?a=b&c=d'), + { + hostname: 'host-from-options.com', + path: '/path-from-options', + port: 1234, + }, + ]) + // Must remove the query string since it's not specified in "options.path" + expect(url.href).toBe('http://host-from-options.com:1234/path-from-options') + expect(options).toMatchObject({ + hostname: 'host-from-options.com', + path: '/path-from-options', + port: 1234, + }) +}) + +it('handles [URL, RequestOptions] where options contain "path" with query string', () => { + const [url, options] = normalizeClientRequestArgs('http:', [ + new URL('http://example.com/path-from-url?a=b&c=d'), + { + path: '/path-from-options?foo=bar&baz=xyz', + }, + ]) + expect(url.href).toBe('http://example.com/path-from-options?foo=bar&baz=xyz') + expect(options).toMatchObject({ + hostname: 'example.com', + path: '/path-from-options?foo=bar&baz=xyz', + }) +}) + +it('handles [RequestOptions, callback] input', () => { + const initialOptions = { + method: 'POST', + protocol: 'https:', + host: 'mswjs.io', + /** + * @see https://github.com/mswjs/msw/issues/705 + */ + origin: 'https://mswjs.io', + path: '/resource', + headers: { + 'Content-Type': 'text/plain', + }, + } + const [url, options, callback] = normalizeClientRequestArgs('https:', [ + initialOptions, + function cb() {}, + ]) + + // URL must be derived from request options. + expect(url.href).toEqual('https://mswjs.io/resource') + + // Request options must be preserved. + expect(options).toMatchObject(initialOptions) + + // Callback must be preserved. + expect(callback).toBeTypeOf('function') + expect(callback?.name).toEqual('cb') +}) + +it('handles [Empty RequestOptions, callback] input', () => { + const [_, options, callback] = normalizeClientRequestArgs('https:', [ + {}, + function cb() {}, + ]) + + expect(options.protocol).toEqual('https:') + + // Callback must be preserved + expect(callback?.name).toEqual('cb') +}) + +/** + * @see https://github.com/mswjs/interceptors/issues/19 + */ +it('handles [PartialRequestOptions, callback] input', () => { + const initialOptions = { + method: 'GET', + port: '50176', + path: '/resource', + host: '127.0.0.1', + ca: undefined, + key: undefined, + pfx: undefined, + cert: undefined, + passphrase: undefined, + agent: false, + } + const [url, options, callback] = normalizeClientRequestArgs('https:', [ + initialOptions, + function cb() {}, + ]) + + // URL must be derived from request options. + expect(url.toJSON()).toEqual( + new URL('https://127.0.0.1:50176/resource').toJSON() + ) + + // Request options must be preserved. + expect(options).toMatchObject(initialOptions) + + // Options protocol must be inferred from the request issuing module. + expect(options.protocol).toEqual('https:') + + // Callback must be preserved. + expect(callback).toBeTypeOf('function') + expect(callback?.name).toEqual('cb') +}) + +it('sets fallback Agent based on the URL protocol', () => { + const [url, options] = normalizeClientRequestArgs('https:', [ + 'https://github.com', + ]) + const agent = options.agent as HttpsAgent + + expect(agent).toBeInstanceOf(HttpsAgent) + expect(agent).toHaveProperty('defaultPort', 443) + expect(agent).toHaveProperty('protocol', url.protocol) +}) + +it('does not set any fallback Agent given "agent: false" option', () => { + const [, options] = normalizeClientRequestArgs('https:', [ + 'https://github.com', + { agent: false }, + ]) + + expect(options.agent).toEqual(false) +}) + +it('sets the default Agent for HTTP request', () => { + const [, options] = normalizeClientRequestArgs('http:', [ + 'http://github.com', + {}, + ]) + + expect(options._defaultAgent).toEqual(httpGlobalAgent) +}) + +it('sets the default Agent for HTTPS request', () => { + const [, options] = normalizeClientRequestArgs('https:', [ + 'https://github.com', + {}, + ]) + + expect(options._defaultAgent).toEqual(httpsGlobalAgent) +}) + +it('preserves a custom default Agent when set', () => { + const [, options] = normalizeClientRequestArgs('https:', [ + 'https://github.com', + { + /** + * @note Intentionally incorrect Agent for HTTPS request. + */ + _defaultAgent: httpGlobalAgent, + }, + ]) + + expect(options._defaultAgent).toEqual(httpGlobalAgent) +}) + +it('merges URL-based RequestOptions with the custom RequestOptions', () => { + const [url, options] = normalizeClientRequestArgs('https:', [ + 'https://github.com/graphql', + { + method: 'GET', + pfx: 'PFX_KEY', + }, + ]) + + expect(url.href).toEqual('https://github.com/graphql') + + // Original request options must be preserved. + expect(options.method).toEqual('GET') + expect(options.pfx).toEqual('PFX_KEY') + + // Other options must be inferred from the URL. + expect(options.protocol).toEqual(url.protocol) + expect(options.hostname).toEqual(url.hostname) + expect(options.path).toEqual(url.pathname) +}) + +it('respects custom "options.path" over URL path', () => { + const [url, options] = normalizeClientRequestArgs('http:', [ + new URL('http://example.com/path-from-url'), + { + path: '/path-from-options', + }, + ]) + + expect(url.href).toBe('http://example.com/path-from-options') + expect(options.protocol).toBe('http:') + expect(options.hostname).toBe('example.com') + expect(options.path).toBe('/path-from-options') +}) + +it('respects custom "options.path" over URL path with query string', () => { + const [url, options] = normalizeClientRequestArgs('http:', [ + new URL('http://example.com/path-from-url?a=b&c=d'), + { + path: '/path-from-options', + }, + ]) + + // Must replace both the path and the query string. + expect(url.href).toBe('http://example.com/path-from-options') + expect(options.protocol).toBe('http:') + expect(options.hostname).toBe('example.com') + expect(options.path).toBe('/path-from-options') +}) + +it('preserves URL query string', () => { + const [url, options] = normalizeClientRequestArgs('http:', [ + new URL('http://example.com:8080/resource?a=b&c=d'), + ]) + + expect(url.href).toBe('http://example.com:8080/resource?a=b&c=d') + expect(options.protocol).toBe('http:') + // expect(options.host).toBe('example.com:8080') + expect(options.hostname).toBe('example.com') + // Query string is a part of the options path. + expect(options.path).toBe('/resource?a=b&c=d') + expect(options.port).toBe(8080) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts new file mode 100644 index 0000000000..03c77453a5 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts @@ -0,0 +1,288 @@ +import { urlToHttpOptions } from 'node:url' +import { + Agent as HttpAgent, + globalAgent as httpGlobalAgent, + IncomingMessage, +} from 'node:http' +import { + RequestOptions, + Agent as HttpsAgent, + globalAgent as httpsGlobalAgent, +} from 'node:https' +import { + /** + * @note Use the Node.js URL instead of the global URL + * because environments like JSDOM may override the global, + * breaking the compatibility with Node.js. + * @see https://github.com/node-fetch/node-fetch/issues/1376#issuecomment-966435555 + */ + URL, + Url as LegacyURL, + parse as parseUrl, +} from 'node:url' +import { Logger } from '@open-draft/logger' +import { + ResolvedRequestOptions, + getUrlByRequestOptions, +} from '../../../utils/getUrlByRequestOptions' +import { cloneObject } from '../../../utils/cloneObject' +import { isObject } from '../../../utils/isObject' + +const logger = new Logger('http normalizeClientRequestArgs') + +export type HttpRequestCallback = (response: IncomingMessage) => void + +export type ClientRequestArgs = + // Request without any arguments is also possible. + | [] + | [string | URL | LegacyURL, HttpRequestCallback?] + | [string | URL | LegacyURL, RequestOptions, HttpRequestCallback?] + | [RequestOptions, HttpRequestCallback?] + +function resolveRequestOptions( + args: ClientRequestArgs, + url: URL +): RequestOptions { + // Calling `fetch` provides only URL to `ClientRequest` + // without any `RequestOptions` or callback. + if (typeof args[1] === 'undefined' || typeof args[1] === 'function') { + logger.info('request options not provided, deriving from the url', url) + return urlToHttpOptions(url) + } + + if (args[1]) { + logger.info('has custom RequestOptions!', args[1]) + const requestOptionsFromUrl = urlToHttpOptions(url) + + logger.info('derived RequestOptions from the URL:', requestOptionsFromUrl) + + /** + * Clone the request options to lock their state + * at the moment they are provided to `ClientRequest`. + * @see https://github.com/mswjs/interceptors/issues/86 + */ + logger.info('cloning RequestOptions...') + const clonedRequestOptions = cloneObject(args[1]) + logger.info('successfully cloned RequestOptions!', clonedRequestOptions) + + return { + ...requestOptionsFromUrl, + ...clonedRequestOptions, + } + } + + logger.info('using an empty object as request options') + return {} as RequestOptions +} + +/** + * Overrides the given `URL` instance with the explicit properties provided + * on the `RequestOptions` object. The options object takes precedence, + * and will replace URL properties like "host", "path", and "port", if specified. + */ +function overrideUrlByRequestOptions(url: URL, options: RequestOptions): URL { + url.host = options.host || url.host + url.hostname = options.hostname || url.hostname + url.port = options.port ? options.port.toString() : url.port + + if (options.path) { + const parsedOptionsPath = parseUrl(options.path, false) + url.pathname = parsedOptionsPath.pathname || '' + url.search = parsedOptionsPath.search || '' + } + + return url +} + +function resolveCallback( + args: ClientRequestArgs +): HttpRequestCallback | undefined { + return typeof args[1] === 'function' ? args[1] : args[2] +} + +export type NormalizedClientRequestArgs = [ + url: URL, + options: ResolvedRequestOptions, + callback?: HttpRequestCallback +] + +/** + * Normalizes parameters given to a `http.request` call + * so it always has a `URL` and `RequestOptions`. + */ +export function normalizeClientRequestArgs( + defaultProtocol: string, + args: ClientRequestArgs +): NormalizedClientRequestArgs { + let url: URL + let options: ResolvedRequestOptions + let callback: HttpRequestCallback | undefined + + logger.info('arguments', args) + logger.info('using default protocol:', defaultProtocol) + + // Support "http.request()" calls without any arguments. + // That call results in a "GET http://localhost" request. + if (args.length === 0) { + const url = new URL('http://localhost') + const options = resolveRequestOptions(args, url) + return [url, options] + } + + // Convert a url string into a URL instance + // and derive request options from it. + if (typeof args[0] === 'string') { + logger.info('first argument is a location string:', args[0]) + + url = new URL(args[0]) + logger.info('created a url:', url) + + const requestOptionsFromUrl = urlToHttpOptions(url) + logger.info('request options from url:', requestOptionsFromUrl) + + options = resolveRequestOptions(args, url) + logger.info('resolved request options:', options) + + callback = resolveCallback(args) + } + // Handle a given URL instance as-is + // and derive request options from it. + else if (args[0] instanceof URL) { + url = args[0] + logger.info('first argument is a URL:', url) + + // Check if the second provided argument is RequestOptions. + // If it is, check if "options.path" was set and rewrite it + // on the input URL. + // Do this before resolving options from the URL below + // to prevent query string from being duplicated in the path. + if (typeof args[1] !== 'undefined' && isObject(args[1])) { + url = overrideUrlByRequestOptions(url, args[1]) + } + + options = resolveRequestOptions(args, url) + logger.info('derived request options:', options) + + callback = resolveCallback(args) + } + // Handle a legacy URL instance and re-normalize from either a RequestOptions object + // or a WHATWG URL. + else if ('hash' in args[0] && !('method' in args[0])) { + const [legacyUrl] = args + logger.info('first argument is a legacy URL:', legacyUrl) + + if (legacyUrl.hostname === null) { + /** + * We are dealing with a relative url, so use the path as an "option" and + * merge in any existing options, giving priority to exising options -- i.e. a path in any + * existing options will take precedence over the one contained in the url. This is consistent + * with the behaviour in ClientRequest. + * @see https://github.com/nodejs/node/blob/d84f1312915fe45fe0febe888db692c74894c382/lib/_http_client.js#L122 + */ + logger.info('given legacy URL is relative (no hostname)') + + return isObject(args[1]) + ? normalizeClientRequestArgs(defaultProtocol, [ + { path: legacyUrl.path, ...args[1] }, + args[2], + ]) + : normalizeClientRequestArgs(defaultProtocol, [ + { path: legacyUrl.path }, + args[1] as HttpRequestCallback, + ]) + } + + logger.info('given legacy url is absolute') + + // We are dealing with an absolute URL, so convert to WHATWG and try again. + const resolvedUrl = new URL(legacyUrl.href) + + return args[1] === undefined + ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl]) + : typeof args[1] === 'function' + ? normalizeClientRequestArgs(defaultProtocol, [resolvedUrl, args[1]]) + : normalizeClientRequestArgs(defaultProtocol, [ + resolvedUrl, + args[1], + args[2], + ]) + } + // Handle a given "RequestOptions" object as-is + // and derive the URL instance from it. + else if (isObject(args[0])) { + options = { ...(args[0] as any) } + logger.info('first argument is RequestOptions:', options) + + // When handling a "RequestOptions" object without an explicit "protocol", + // infer the protocol from the request issuing module (http/https). + options.protocol = options.protocol || defaultProtocol + logger.info('normalized request options:', options) + + url = getUrlByRequestOptions(options) + logger.info('created a URL from RequestOptions:', url.href) + + callback = resolveCallback(args) + } else { + throw new Error( + `Failed to construct ClientRequest with these parameters: ${args}` + ) + } + + options.protocol = options.protocol || url.protocol + options.method = options.method || 'GET' + + /** + * Infer a fallback agent from the URL protocol. + * The interception is done on the "ClientRequest" level ("NodeClientRequest") + * and it may miss the correct agent. Always align the agent + * with the URL protocol, if not provided. + * + * @note Respect the "agent: false" value. + */ + if (typeof options.agent === 'undefined') { + const agent = + options.protocol === 'https:' + ? new HttpsAgent({ + rejectUnauthorized: options.rejectUnauthorized, + }) + : new HttpAgent() + + options.agent = agent + logger.info('resolved fallback agent:', agent) + } + + /** + * Ensure that the default Agent is always set. + * This prevents the protocol mismatch for requests with { agent: false }, + * where the global Agent is inferred. + * @see https://github.com/mswjs/msw/issues/1150 + * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L130 + * @see https://github.com/nodejs/node/blob/418ff70b810f0e7112d48baaa72932a56cfa213b/lib/_http_client.js#L157-L159 + */ + if (!options._defaultAgent) { + logger.info( + 'has no default agent, setting the default agent for "%s"', + options.protocol + ) + + options._defaultAgent = + options.protocol === 'https:' ? httpsGlobalAgent : httpGlobalAgent + } + + logger.info('successfully resolved url:', url.href) + logger.info('successfully resolved options:', options) + logger.info('successfully resolved callback:', callback) + + /** + * @note If the user-provided URL is not a valid URL in Node.js, + * (e.g. the one provided by the JSDOM polyfills), case it to + * string. Otherwise, this throws on Node.js incompatibility + * (`ERR_INVALID_ARG_TYPE` on the connection listener) + * @see https://github.com/node-fetch/node-fetch/issues/1376#issuecomment-966435555 + */ + if (!(url instanceof URL)) { + url = (url as any).toString() + } + + return [url, options, callback] +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts new file mode 100644 index 0000000000..7507126086 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/recordRawHeaders.test.ts @@ -0,0 +1,258 @@ +// @vitest-environment node +import { it, expect, afterEach } from 'vitest' +import { + recordRawFetchHeaders, + restoreHeadersPrototype, + getRawFetchHeaders, +} from './recordRawHeaders' + +const url = 'http://localhost' + +afterEach(() => { + restoreHeadersPrototype() +}) + +it('returns an empty list if no headers were set', () => { + expect(getRawFetchHeaders(new Headers())).toEqual([]) + expect(getRawFetchHeaders(new Headers(undefined))).toEqual([]) + expect(getRawFetchHeaders(new Headers({}))).toEqual([]) + expect(getRawFetchHeaders(new Headers([]))).toEqual([]) + expect(getRawFetchHeaders(new Request(url).headers)).toEqual([]) + expect(getRawFetchHeaders(new Response().headers)).toEqual([]) +}) + +it('records raw headers (Headers / object as init)', () => { + recordRawFetchHeaders() + const headers = new Headers({ + 'Content-Type': 'application/json', + 'X-My-Header': '1', + }) + + expect(getRawFetchHeaders(headers)).toEqual([ + ['Content-Type', 'application/json'], + ['X-My-Header', '1'], + ]) + expect(Object.fromEntries(headers)).toEqual({ + 'content-type': 'application/json', + 'x-my-header': '1', + }) +}) + +it('records raw headers (Headers / array as init)', () => { + recordRawFetchHeaders() + const headers = new Headers([['X-My-Header', '1']]) + + expect(getRawFetchHeaders(headers)).toEqual([['X-My-Header', '1']]) + expect(Object.fromEntries(headers)).toEqual({ + 'x-my-header': '1', + }) +}) + +it('records raw headers (Headers / Headers as init', () => { + recordRawFetchHeaders() + const headers = new Headers([['X-My-Header', '1']]) + + expect(getRawFetchHeaders(new Headers(headers))).toEqual([ + ['X-My-Header', '1'], + ]) +}) + +it('records raw headers added via ".set()"', () => { + recordRawFetchHeaders() + const headers = new Headers([['X-My-Header', '1']]) + headers.set('X-Another-Header', '2') + + expect(getRawFetchHeaders(headers)).toEqual([ + ['X-My-Header', '1'], + ['X-Another-Header', '2'], + ]) +}) + +it('records raw headers added via ".append()"', () => { + recordRawFetchHeaders() + const headers = new Headers([['X-My-Header', '1']]) + headers.append('X-My-Header', '2') + + expect(getRawFetchHeaders(headers)).toEqual([ + ['X-My-Header', '1'], + ['X-My-Header', '2'], + ]) +}) + +it('deletes the header when called ".delete()"', () => { + const headers = new Headers([['X-My-Header', '1']]) + headers.delete('X-My-Header') + + expect(getRawFetchHeaders(headers)).toEqual([]) +}) + +it('records raw headers (Request / object as init)', () => { + recordRawFetchHeaders() + const request = new Request(url, { + headers: { + 'Content-Type': 'application/json', + 'X-My-Header': '1', + }, + }) + + expect(getRawFetchHeaders(request.headers)).toEqual([ + ['Content-Type', 'application/json'], + ['X-My-Header', '1'], + ]) +}) + +it('records raw headers (Request / array as init)', () => { + recordRawFetchHeaders() + const request = new Request(url, { + headers: [['X-My-Header', '1']], + }) + + expect(getRawFetchHeaders(request.headers)).toEqual([['X-My-Header', '1']]) +}) + +it('records raw headers (Request / Headers as init)', () => { + recordRawFetchHeaders() + const headers = new Headers([['X-My-Header', '1']]) + const request = new Request(url, { headers }) + + expect(getRawFetchHeaders(request.headers)).toEqual([['X-My-Header', '1']]) +}) + +it('records raw headers (Reqest / Request as init)', () => { + recordRawFetchHeaders() + const init = new Request(url, { headers: [['X-My-Header', '1']] }) + const request = new Request(init) + + expect(getRawFetchHeaders(request.headers)).toEqual([['X-My-Header', '1']]) +}) + +it('preserves headers instanceof (Request / Request as init)', () => { + recordRawFetchHeaders() + const init = new Request(url, { headers: [['X-My-Header', '1']] }) + new Request(init) + expect(init.headers).toBeInstanceOf(Headers) +}) + +it('preserves headers instanceof (Request / Request with Headers as init)', () => { + recordRawFetchHeaders() + const headers = new Headers([['X-My-Header', '1']]) + const init = new Request(url, { headers }) + new Request(init) + expect(init.headers).toBeInstanceOf(Headers) +}) + +it('preserves headers instanceof (Response / Response with Headers as init)', () => { + recordRawFetchHeaders() + const init = { headers: new Headers([['X-My-Header', '1']]) } + new Response(url, init) + expect(init.headers).toBeInstanceOf(Headers) +}) + +it('records raw headers (Request / Request+Headers as init)', () => { + recordRawFetchHeaders() + const init = new Request(url, { headers: [['X-My-Header', '1']] }) + expect(getRawFetchHeaders(init.headers)).toEqual([['X-My-Header', '1']]) + + const request = new Request(init, { + headers: new Headers([['X-Another-Header', '2']]), + }) + + // Must merge the raw headers from the request init + // and the request instance itself. + expect(getRawFetchHeaders(request.headers)).toEqual([ + ['X-My-Header', '1'], + ['X-Another-Header', '2'], + ]) +}) + +it('records raw headers (Response / object as init)', () => { + recordRawFetchHeaders() + const response = new Response(null, { + headers: { + 'Content-Type': 'application/json', + 'X-My-Header': '1', + }, + }) + + expect(getRawFetchHeaders(response.headers)).toEqual([ + ['Content-Type', 'application/json'], + ['X-My-Header', '1'], + ]) +}) + +it('records raw headers (Response / array as init)', () => { + recordRawFetchHeaders() + const response = new Response(null, { + headers: [['X-My-Header', '1']], + }) + + expect(getRawFetchHeaders(response.headers)).toEqual([['X-My-Header', '1']]) +}) + +it('records raw headers (Response / Headers as init)', () => { + recordRawFetchHeaders() + const headers = new Headers([['X-My-Header', '1']]) + const response = new Response(null, { headers }) + + expect(getRawFetchHeaders(response.headers)).toEqual([['X-My-Header', '1']]) +}) + +it('stops recording once the patches are restored', () => { + restoreHeadersPrototype() + + const headers = new Headers({ 'X-My-Header': '1' }) + // Must return the normalized headers (no access to raw headers). + expect(getRawFetchHeaders(headers)).toEqual([['x-my-header', '1']]) +}) + +it('overrides an existing header when calling ".set()"', () => { + recordRawFetchHeaders() + const headers = new Headers([['a', '1']]) + expect(headers.get('a')).toBe('1') + + headers.set('a', '2') + expect(headers.get('a')).toBe('2') + + const headersClone = new Headers(headers) + expect(headersClone.get('a')).toBe('2') +}) + +it('overrides an existing multi-value header when calling ".set()"', () => { + recordRawFetchHeaders() + const headers = new Headers([ + ['a', '1'], + ['a', '2'], + ]) + expect(headers.get('a')).toBe('1, 2') + + headers.set('a', '3') + expect(headers.get('a')).toBe('3') +}) + +it('does not throw on using Headers before recording', () => { + // If the consumer constructs a Headers instance before + // the interceptor is enabled, it will have no internal symbol set. + const headers = new Headers() + recordRawFetchHeaders() + const request = new Request(url, { headers }) + + expect(getRawFetchHeaders(request.headers)).toEqual([]) + + request.headers.set('X-My-Header', '1') + expect(getRawFetchHeaders(request.headers)).toEqual([['X-My-Header', '1']]) +}) + +/** + * @see https://github.com/mswjs/interceptors/issues/681 + */ +it('isolates headers between different headers instances', async () => { + recordRawFetchHeaders() + const original = new Headers() + const firstClone = new Headers(original) + firstClone.set('Content-Type', 'application/json') + const secondClone = new Headers(original) + + expect(original.get('Content-Type')).toBeNull() + expect(firstClone.get('Content-Type')).toBe('application/json') + expect(secondClone.get('Content-Type')).toBeNull() +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/recordRawHeaders.ts b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/recordRawHeaders.ts new file mode 100644 index 0000000000..80902d5036 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/utils/recordRawHeaders.ts @@ -0,0 +1,262 @@ +type HeaderTuple = [string, string] +type RawHeaders = Array +type SetHeaderBehavior = 'set' | 'append' + +const kRawHeaders = Symbol('kRawHeaders') +const kRestorePatches = Symbol('kRestorePatches') + +function recordRawHeader( + headers: Headers, + args: HeaderTuple, + behavior: SetHeaderBehavior +) { + ensureRawHeadersSymbol(headers, []) + const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders + + if (behavior === 'set') { + // When recording a set header, ensure we remove any matching existing headers. + for (let index = rawHeaders.length - 1; index >= 0; index--) { + if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) { + rawHeaders.splice(index, 1) + } + } + } + + rawHeaders.push(args) +} + +/** + * Define the raw headers symbol on the given `Headers` instance. + * If the symbol already exists, this function does nothing. + */ +function ensureRawHeadersSymbol( + headers: Headers, + rawHeaders: RawHeaders +): void { + if (Reflect.has(headers, kRawHeaders)) { + return + } + + defineRawHeadersSymbol(headers, rawHeaders) +} + +/** + * Define the raw headers symbol on the given `Headers` instance. + * If the symbol already exists, it gets overridden. + */ +function defineRawHeadersSymbol(headers: Headers, rawHeaders: RawHeaders) { + Object.defineProperty(headers, kRawHeaders, { + value: rawHeaders, + enumerable: false, + // Mark the symbol as configurable so its value can be overridden. + // Overrides happen when merging raw headers from multiple sources. + // E.g. new Request(new Request(url, { headers }), { headers }) + configurable: true, + }) +} + +/** + * Patch the global `Headers` class to store raw headers. + * This is for compatibility with `IncomingMessage.prototype.rawHeaders`. + * + * @note Node.js has their own raw headers symbol but it + * only records the first header name in case of multi-value headers. + * Any other headers are normalized before comparing. This makes it + * incompatible with the `rawHeaders` format. + * + * let h = new Headers() + * h.append('X-Custom', 'one') + * h.append('x-custom', 'two') + * h[Symbol('headers map')] // Map { 'X-Custom' => 'one, two' } + */ +export function recordRawFetchHeaders() { + // Prevent patching the Headers prototype multiple times. + if (Reflect.get(Headers, kRestorePatches)) { + return Reflect.get(Headers, kRestorePatches) + } + + const { + Headers: OriginalHeaders, + Request: OriginalRequest, + Response: OriginalResponse, + } = globalThis + const { set, append, delete: headersDeleteMethod } = Headers.prototype + + Object.defineProperty(Headers, kRestorePatches, { + value: () => { + Headers.prototype.set = set + Headers.prototype.append = append + Headers.prototype.delete = headersDeleteMethod + globalThis.Headers = OriginalHeaders + + globalThis.Request = OriginalRequest + globalThis.Response = OriginalResponse + + Reflect.deleteProperty(Headers, kRestorePatches) + }, + enumerable: false, + /** + * @note Mark this property as configurable + * so we can delete it using `Reflect.delete` during cleanup. + */ + configurable: true, + }) + + Object.defineProperty(globalThis, 'Headers', { + enumerable: true, + writable: true, + value: new Proxy(Headers, { + construct(target, args, newTarget) { + const headersInit = args[0] || [] + + if ( + headersInit instanceof Headers && + Reflect.has(headersInit, kRawHeaders) + ) { + const headers = Reflect.construct( + target, + [Reflect.get(headersInit, kRawHeaders)], + newTarget + ) + ensureRawHeadersSymbol(headers, [ + /** + * @note Spread the retrieved headers to clone them. + * This prevents multiple Headers instances from pointing + * at the same internal "rawHeaders" array. + */ + ...Reflect.get(headersInit, kRawHeaders), + ]) + return headers + } + + const headers = Reflect.construct(target, args, newTarget) + + // Request/Response constructors will set the symbol + // upon creating a new instance, using the raw developer + // input as the raw headers. Skip the symbol altogether + // in those cases because the input to Headers will be normalized. + if (!Reflect.has(headers, kRawHeaders)) { + const rawHeadersInit = Array.isArray(headersInit) + ? headersInit + : Object.entries(headersInit) + ensureRawHeadersSymbol(headers, rawHeadersInit) + } + + return headers + }, + }), + }) + + Headers.prototype.set = new Proxy(Headers.prototype.set, { + apply(target, thisArg, args: HeaderTuple) { + recordRawHeader(thisArg, args, 'set') + return Reflect.apply(target, thisArg, args) + }, + }) + + Headers.prototype.append = new Proxy(Headers.prototype.append, { + apply(target, thisArg, args: HeaderTuple) { + recordRawHeader(thisArg, args, 'append') + return Reflect.apply(target, thisArg, args) + }, + }) + + Headers.prototype.delete = new Proxy(Headers.prototype.delete, { + apply(target, thisArg, args: [string]) { + const rawHeaders = Reflect.get(thisArg, kRawHeaders) as RawHeaders + + if (rawHeaders) { + for (let index = rawHeaders.length - 1; index >= 0; index--) { + if (rawHeaders[index][0].toLowerCase() === args[0].toLowerCase()) { + rawHeaders.splice(index, 1) + } + } + } + + return Reflect.apply(target, thisArg, args) + }, + }) + + Object.defineProperty(globalThis, 'Request', { + enumerable: true, + writable: true, + value: new Proxy(Request, { + construct(target, args, newTarget) { + const request = Reflect.construct(target, args, newTarget) + const inferredRawHeaders: RawHeaders = [] + + // Infer raw headers from a `Request` instance used as init. + if (typeof args[0] === 'object' && args[0].headers != null) { + inferredRawHeaders.push(...inferRawHeaders(args[0].headers)) + } + + // Infer raw headers from the "headers" init argument. + if (typeof args[1] === 'object' && args[1].headers != null) { + inferredRawHeaders.push(...inferRawHeaders(args[1].headers)) + } + + if (inferredRawHeaders.length > 0) { + ensureRawHeadersSymbol(request.headers, inferredRawHeaders) + } + + return request + }, + }), + }) + + Object.defineProperty(globalThis, 'Response', { + enumerable: true, + writable: true, + value: new Proxy(Response, { + construct(target, args, newTarget) { + const response = Reflect.construct(target, args, newTarget) + + if (typeof args[1] === 'object' && args[1].headers != null) { + ensureRawHeadersSymbol( + response.headers, + inferRawHeaders(args[1].headers) + ) + } + + return response + }, + }), + }) +} + +export function restoreHeadersPrototype() { + if (!Reflect.get(Headers, kRestorePatches)) { + return + } + + Reflect.get(Headers, kRestorePatches)() +} + +export function getRawFetchHeaders(headers: Headers): RawHeaders { + // If the raw headers recording failed for some reason, + // use the normalized header entries instead. + if (!Reflect.has(headers, kRawHeaders)) { + return Array.from(headers.entries()) + } + + const rawHeaders = Reflect.get(headers, kRawHeaders) as RawHeaders + return rawHeaders.length > 0 ? rawHeaders : Array.from(headers.entries()) +} + +/** + * Infers the raw headers from the given `HeadersInit` provided + * to the Request/Response constructor. + * + * If the `init.headers` is a Headers instance, use it directly. + * That means the headers were created standalone and already have + * the raw headers stored. + * If the `init.headers` is a HeadersInit, create a new Headers + * instace out of it. + */ +function inferRawHeaders(headers: HeadersInit): RawHeaders { + if (headers instanceof Headers) { + return Reflect.get(headers, kRawHeaders) || [] + } + + return Reflect.get(new Headers(headers), kRawHeaders) +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/Socket/MockSocket.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/Socket/MockSocket.test.ts new file mode 100644 index 0000000000..61235cf363 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/Socket/MockSocket.test.ts @@ -0,0 +1,264 @@ +/** + * @vitest-environment node + */ +import { Socket } from 'node:net' +import { vi, it, expect } from 'vitest' +import { MockSocket } from './MockSocket' + +it(`keeps the socket connecting until it's destroyed`, () => { + const socket = new MockSocket({ + write: vi.fn(), + read: vi.fn(), + }) + + expect(socket.connecting).toBe(true) + + socket.destroy() + expect(socket.connecting).toBe(false) +}) + +it('calls the "write" on "socket.write()"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + socket.write() + expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined) +}) + +it('calls the "write" on "socket.write(chunk)"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + socket.write('hello') + expect(writeCallback).toHaveBeenCalledWith('hello', undefined, undefined) +}) + +it('calls the "write" on "socket.write(chunk, encoding)"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + socket.write('hello', 'utf8') + expect(writeCallback).toHaveBeenCalledWith('hello', 'utf8', undefined) +}) + +it('calls the "write" on "socket.write(chunk, encoding, callback)"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + const callback = vi.fn() + socket.write('hello', 'utf8', callback) + expect(writeCallback).toHaveBeenCalledWith('hello', 'utf8', callback) +}) + +it('calls the "write" on "socket.end()"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + socket.end() + expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined) +}) + +it('calls the "write" on "socket.end(chunk)"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + socket.end('final') + expect(writeCallback).toHaveBeenCalledWith('final', undefined, undefined) +}) + +it('calls the "write" on "socket.end(chunk, encoding)"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + socket.end('final', 'utf8') + expect(writeCallback).toHaveBeenCalledWith('final', 'utf8', undefined) +}) + +it('calls the "write" on "socket.end(chunk, encoding, callback)"', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + const callback = vi.fn() + socket.end('final', 'utf8', callback) + expect(writeCallback).toHaveBeenCalledWith('final', 'utf8', callback) +}) + +it('calls the "write" on "socket.end()" without any arguments', () => { + const writeCallback = vi.fn() + const socket = new MockSocket({ + write: writeCallback, + read: vi.fn(), + }) + + socket.end() + expect(writeCallback).toHaveBeenCalledWith(undefined, undefined, undefined) +}) + +it('emits "finished" on .end() without any arguments', async () => { + const finishListener = vi.fn() + const socket = new MockSocket({ + write: vi.fn(), + read: vi.fn(), + }) + socket.on('finish', finishListener) + socket.end() + + await vi.waitFor(() => { + expect(finishListener).toHaveBeenCalledTimes(1) + }) +}) + +it('calls the "read" on "socket.read(chunk)"', () => { + const readCallback = vi.fn() + const socket = new MockSocket({ + write: vi.fn(), + read: readCallback, + }) + + socket.push('hello') + expect(readCallback).toHaveBeenCalledWith('hello', undefined) +}) + +it('calls the "read" on "socket.read(chunk, encoding)"', () => { + const readCallback = vi.fn() + const socket = new MockSocket({ + write: vi.fn(), + read: readCallback, + }) + + socket.push('world', 'utf8') + expect(readCallback).toHaveBeenCalledWith('world', 'utf8') +}) + +it('calls the "read" on "socket.read(null)"', () => { + const readCallback = vi.fn() + const socket = new MockSocket({ + write: vi.fn(), + read: readCallback, + }) + + socket.push(null) + expect(readCallback).toHaveBeenCalledWith(null, undefined) +}) + +it('updates the writable state on "socket.end()"', async () => { + const finishListener = vi.fn() + const endListener = vi.fn() + const socket = new MockSocket({ + write: vi.fn(), + read: vi.fn(), + }) + socket.on('finish', finishListener) + socket.on('end', endListener) + + expect(socket.writable).toBe(true) + expect(socket.writableEnded).toBe(false) + expect(socket.writableFinished).toBe(false) + + socket.write('hello') + // Finish the writable stream. + socket.end() + + expect(socket.writable).toBe(false) + expect(socket.writableEnded).toBe(true) + + // The "finish" event is emitted when writable is done. + // I.e. "socket.end()" is called. + await vi.waitFor(() => { + expect(finishListener).toHaveBeenCalledTimes(1) + }) + expect(socket.writableFinished).toBe(true) +}) + +it('updates the readable state on "socket.push(null)"', async () => { + const endListener = vi.fn() + const socket = new MockSocket({ + write: vi.fn(), + read: vi.fn(), + }) + socket.on('end', endListener) + + expect(socket.readable).toBe(true) + expect(socket.readableEnded).toBe(false) + + socket.push('hello') + socket.push(null) + + expect(socket.readable).toBe(true) + expect(socket.readableEnded).toBe(false) + + // Read the data to free the buffer and + // make Socket emit "end". + socket.read() + + await vi.waitFor(() => { + expect(endListener).toHaveBeenCalledTimes(1) + }) + expect(socket.readable).toBe(false) + expect(socket.readableEnded).toBe(true) +}) + +it('updates the readable/writable state on "socket.destroy()"', async () => { + const finishListener = vi.fn() + const endListener = vi.fn() + const closeListener = vi.fn() + const socket = new MockSocket({ + write: vi.fn(), + read: vi.fn(), + }) + socket.on('finish', finishListener) + socket.on('end', endListener) + socket.on('close', closeListener) + + expect(socket.writable).toBe(true) + expect(socket.writableEnded).toBe(false) + expect(socket.writableFinished).toBe(false) + expect(socket.readable).toBe(true) + + socket.destroy() + + expect(socket.writable).toBe(false) + // The ".end()" wasn't called. + expect(socket.writableEnded).toBe(false) + expect(socket.writableFinished).toBe(false) + expect(socket.readable).toBe(false) + + await vi.waitFor(() => { + expect(closeListener).toHaveBeenCalledTimes(1) + }) + + // Neither "finish" nor "end" events are emitted + // when you destroy the stream. If you want those, + // call ".end()", then destroy the stream. + expect(finishListener).not.toHaveBeenCalled() + expect(endListener).not.toHaveBeenCalled() + expect(socket.writableFinished).toBe(false) + + // The "end" event was never emitted so "readableEnded" + // remains false. + expect(socket.readableEnded).toBe(false) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/Socket/MockSocket.ts b/node_modules/@mswjs/interceptors/src/interceptors/Socket/MockSocket.ts new file mode 100644 index 0000000000..5bcc42eead --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/Socket/MockSocket.ts @@ -0,0 +1,58 @@ +import net from 'node:net' +import { + normalizeSocketWriteArgs, + type WriteArgs, + type WriteCallback, +} from './utils/normalizeSocketWriteArgs' + +export interface MockSocketOptions { + write: ( + chunk: Buffer | string, + encoding: BufferEncoding | undefined, + callback?: WriteCallback + ) => void + + read: (chunk: Buffer, encoding: BufferEncoding | undefined) => void +} + +export class MockSocket extends net.Socket { + public connecting: boolean + + constructor(protected readonly options: MockSocketOptions) { + super() + this.connecting = false + this.connect() + + this._final = (callback) => { + callback(null) + } + } + + public connect() { + // The connection will remain pending until + // the consumer decides to handle it. + this.connecting = true + return this + } + + public write(...args: Array): boolean { + const [chunk, encoding, callback] = normalizeSocketWriteArgs( + args as WriteArgs + ) + this.options.write(chunk, encoding, callback) + return true + } + + public end(...args: Array) { + const [chunk, encoding, callback] = normalizeSocketWriteArgs( + args as WriteArgs + ) + this.options.write(chunk, encoding, callback) + return super.end.apply(this, args as any) + } + + public push(chunk: any, encoding?: BufferEncoding): boolean { + this.options.read(chunk, encoding) + return super.push(chunk, encoding) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts b/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts new file mode 100644 index 0000000000..6a4f33adba --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts @@ -0,0 +1,26 @@ +export function baseUrlFromConnectionOptions(options: any): URL { + if ('href' in options) { + return new URL(options.href) + } + + const protocol = options.port === 443 ? 'https:' : 'http:' + const host = options.host + + const url = new URL(`${protocol}//${host}`) + + if (options.port) { + url.port = options.port.toString() + } + + if (options.path) { + url.pathname = options.path + } + + if (options.auth) { + const [username, password] = options.auth.split(':') + url.username = username + url.password = password + } + + return url +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts new file mode 100644 index 0000000000..32f2e1d5a8 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts @@ -0,0 +1,52 @@ +/** + * @vitest-environment node + */ +import { it, expect } from 'vitest' +import { normalizeSocketWriteArgs } from './normalizeSocketWriteArgs' + +it('normalizes .write()', () => { + expect(normalizeSocketWriteArgs([undefined])).toEqual([ + undefined, + undefined, + undefined, + ]) + expect(normalizeSocketWriteArgs([null])).toEqual([null, undefined, undefined]) +}) + +it('normalizes .write(chunk)', () => { + expect(normalizeSocketWriteArgs([Buffer.from('hello')])).toEqual([ + Buffer.from('hello'), + undefined, + undefined, + ]) + expect(normalizeSocketWriteArgs(['hello'])).toEqual([ + 'hello', + undefined, + undefined, + ]) + expect(normalizeSocketWriteArgs([null])).toEqual([null, undefined, undefined]) +}) + +it('normalizes .write(chunk, encoding)', () => { + expect(normalizeSocketWriteArgs([Buffer.from('hello'), 'utf8'])).toEqual([ + Buffer.from('hello'), + 'utf8', + undefined, + ]) +}) + +it('normalizes .write(chunk, callback)', () => { + const callback = () => {} + expect(normalizeSocketWriteArgs([Buffer.from('hello'), callback])).toEqual([ + Buffer.from('hello'), + undefined, + callback, + ]) +}) + +it('normalizes .write(chunk, encoding, callback)', () => { + const callback = () => {} + expect( + normalizeSocketWriteArgs([Buffer.from('hello'), 'utf8', callback]) + ).toEqual([Buffer.from('hello'), 'utf8', callback]) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts b/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts new file mode 100644 index 0000000000..03a3e9c054 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts @@ -0,0 +1,33 @@ +export type WriteCallback = (error?: Error | null) => void + +export type WriteArgs = + | [chunk: unknown, callback?: WriteCallback] + | [chunk: unknown, encoding: BufferEncoding, callback?: WriteCallback] + +export type NormalizedSocketWriteArgs = [ + chunk: any, + encoding?: BufferEncoding, + callback?: WriteCallback, +] + +/** + * Normalizes the arguments provided to the `Writable.prototype.write()` + * and `Writable.prototype.end()`. + */ +export function normalizeSocketWriteArgs( + args: WriteArgs +): NormalizedSocketWriteArgs { + const normalized: NormalizedSocketWriteArgs = [args[0], undefined, undefined] + + if (typeof args[1] === 'string') { + normalized[1] = args[1] + } else if (typeof args[1] === 'function') { + normalized[2] = args[1] + } + + if (typeof args[2] === 'function') { + normalized[2] = args[2] + } + + return normalized +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketClassTransport.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketClassTransport.ts new file mode 100644 index 0000000000..70f2166584 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketClassTransport.ts @@ -0,0 +1,116 @@ +import { bindEvent } from './utils/bindEvent' +import { + StrictEventListenerOrEventListenerObject, + WebSocketData, + WebSocketTransport, + WebSocketTransportEventMap, +} from './WebSocketTransport' +import { kOnSend, kClose, WebSocketOverride } from './WebSocketOverride' +import { CancelableMessageEvent, CloseEvent } from './utils/events' + +/** + * Abstraction over the given mock `WebSocket` instance that allows + * for controlling that instance (e.g. sending and receiving messages). + */ +export class WebSocketClassTransport + extends EventTarget + implements WebSocketTransport +{ + constructor(protected readonly socket: WebSocketOverride) { + super() + + // Emit the "close" event on the transport if the close + // originates from the WebSocket client. E.g. the application + // calls "ws.close()", not the interceptor. + this.socket.addEventListener('close', (event) => { + this.dispatchEvent(bindEvent(this.socket, new CloseEvent('close', event))) + }) + + /** + * Emit the "outgoing" event on the transport + * whenever the WebSocket client sends data ("ws.send()"). + */ + this.socket[kOnSend] = (data) => { + this.dispatchEvent( + bindEvent( + this.socket, + // Dispatch this as cancelable because "client" connection + // re-creates this message event (cannot dispatch the same event). + new CancelableMessageEvent('outgoing', { + data, + origin: this.socket.url, + cancelable: true, + }) + ) + ) + } + } + + public addEventListener( + type: EventType, + callback: StrictEventListenerOrEventListenerObject< + WebSocketTransportEventMap[EventType] + > | null, + options?: boolean | AddEventListenerOptions + ): void { + return super.addEventListener(type, callback as EventListener, options) + } + + public dispatchEvent( + event: WebSocketTransportEventMap[EventType] + ): boolean { + return super.dispatchEvent(event) + } + + public send(data: WebSocketData): void { + queueMicrotask(() => { + if ( + this.socket.readyState === this.socket.CLOSING || + this.socket.readyState === this.socket.CLOSED + ) { + return + } + + const dispatchEvent = () => { + this.socket.dispatchEvent( + bindEvent( + /** + * @note Setting this event's "target" to the + * WebSocket override instance is important. + * This way it can tell apart original incoming events + * (must be forwarded to the transport) from the + * mocked message events like the one below + * (must be dispatched on the client instance). + */ + this.socket, + new MessageEvent('message', { + data, + origin: this.socket.url, + }) + ) + ) + } + + if (this.socket.readyState === this.socket.CONNECTING) { + this.socket.addEventListener( + 'open', + () => { + dispatchEvent() + }, + { once: true } + ) + } else { + dispatchEvent() + } + }) + } + + public close(code: number, reason?: string): void { + /** + * @note Call the internal close method directly + * to allow closing the connection with the status codes + * that are non-configurable by the user (> 1000 <= 1015). + */ + this.socket[kClose](code, reason) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketClientConnection.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketClientConnection.ts new file mode 100644 index 0000000000..0e1749cf7f --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketClientConnection.ts @@ -0,0 +1,138 @@ +import type { WebSocketData, WebSocketTransport } from './WebSocketTransport' +import type { WebSocketEventListener } from './WebSocketOverride' +import { bindEvent } from './utils/bindEvent' +import { CancelableMessageEvent, CloseEvent } from './utils/events' +import { createRequestId } from '../../createRequestId' + +const kEmitter = Symbol('kEmitter') +const kBoundListener = Symbol('kBoundListener') + +interface WebSocketClientEventMap { + message: MessageEvent + close: CloseEvent +} + +export interface WebSocketClientConnectionProtocol { + id: string + url: URL + send(data: WebSocketData): void + close(code?: number, reason?: string): void +} + +/** + * The WebSocket client instance represents an incoming + * client connection. The user can control the connection, + * send and receive events. + */ +export class WebSocketClientConnection + implements WebSocketClientConnectionProtocol +{ + public readonly id: string + public readonly url: URL + + private [kEmitter]: EventTarget + + constructor( + public readonly socket: WebSocket, + private readonly transport: WebSocketTransport + ) { + this.id = createRequestId() + this.url = new URL(socket.url) + this[kEmitter] = new EventTarget() + + // Emit outgoing client data ("ws.send()") as "message" + // events on the "client" connection. + this.transport.addEventListener('outgoing', (event) => { + const message = bindEvent( + this.socket, + new CancelableMessageEvent('message', { + data: event.data, + origin: event.origin, + cancelable: true, + }) + ) + + this[kEmitter].dispatchEvent(message) + + // This is a bit silly but forward the cancellation state + // of the "client" message event to the "outgoing" transport event. + // This way, other agens (like "server" connection) can know + // whether the client listener has pervented the default. + if (message.defaultPrevented) { + event.preventDefault() + } + }) + + /** + * Emit the "close" event on the "client" connection + * whenever the underlying transport is closed. + * @note "client.close()" does NOT dispatch the "close" + * event on the WebSocket because it uses non-configurable + * close status code. Thus, we listen to the transport + * instead of the WebSocket's "close" event. + */ + this.transport.addEventListener('close', (event) => { + this[kEmitter].dispatchEvent( + bindEvent(this.socket, new CloseEvent('close', event)) + ) + }) + } + + /** + * Listen for the outgoing events from the connected WebSocket client. + */ + public addEventListener( + type: EventType, + listener: WebSocketEventListener, + options?: AddEventListenerOptions | boolean + ): void { + if (!Reflect.has(listener, kBoundListener)) { + const boundListener = listener.bind(this.socket) + + // Store the bound listener on the original listener + // so the exact bound function can be accessed in "removeEventListener()". + Object.defineProperty(listener, kBoundListener, { + value: boundListener, + enumerable: false, + configurable: false, + }) + } + + this[kEmitter].addEventListener( + type, + Reflect.get(listener, kBoundListener) as EventListener, + options + ) + } + + /** + * Removes the listener for the given event. + */ + public removeEventListener( + event: EventType, + listener: WebSocketEventListener, + options?: EventListenerOptions | boolean + ): void { + this[kEmitter].removeEventListener( + event, + Reflect.get(listener, kBoundListener) as EventListener, + options + ) + } + + /** + * Send data to the connected client. + */ + public send(data: WebSocketData): void { + this.transport.send(data) + } + + /** + * Close the WebSocket connection. + * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1). + * @param {string} reason A custom connection close reason. + */ + public close(code?: number, reason?: string): void { + this.transport.close(code, reason) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketOverride.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketOverride.ts new file mode 100644 index 0000000000..8edb17289d --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketOverride.ts @@ -0,0 +1,251 @@ +import { invariant } from 'outvariant' +import type { WebSocketData } from './WebSocketTransport' +import { bindEvent } from './utils/bindEvent' +import { CloseEvent } from './utils/events' +import { DeferredPromise } from '@open-draft/deferred-promise' + +export type WebSocketEventListener< + EventType extends WebSocketEventMap[keyof WebSocketEventMap] = Event +> = (this: WebSocket, event: EventType) => void + +const WEBSOCKET_CLOSE_CODE_RANGE_ERROR = + 'InvalidAccessError: close code out of user configurable range' + +export const kPassthroughPromise = Symbol('kPassthroughPromise') +export const kOnSend = Symbol('kOnSend') +export const kClose = Symbol('kClose') + +export class WebSocketOverride extends EventTarget implements WebSocket { + static readonly CONNECTING = 0 + static readonly OPEN = 1 + static readonly CLOSING = 2 + static readonly CLOSED = 3 + readonly CONNECTING = 0 + readonly OPEN = 1 + readonly CLOSING = 2 + readonly CLOSED = 3 + + public url: string + public protocol: string + public extensions: string + public binaryType: BinaryType + public readyState: number + public bufferedAmount: number + + private _onopen: WebSocketEventListener | null = null + private _onmessage: WebSocketEventListener< + MessageEvent + > | null = null + private _onerror: WebSocketEventListener | null = null + private _onclose: WebSocketEventListener | null = null + + private [kPassthroughPromise]: DeferredPromise + private [kOnSend]?: (data: WebSocketData) => void + + constructor(url: string | URL, protocols?: string | Array) { + super() + this.url = url.toString() + this.protocol = '' + this.extensions = '' + this.binaryType = 'blob' + this.readyState = this.CONNECTING + this.bufferedAmount = 0 + + this[kPassthroughPromise] = new DeferredPromise() + + queueMicrotask(async () => { + if (await this[kPassthroughPromise]) { + return + } + + this.protocol = + typeof protocols === 'string' + ? protocols + : Array.isArray(protocols) && protocols.length > 0 + ? protocols[0] + : '' + + /** + * @note Check that nothing has prevented this connection + * (e.g. called `client.close()` in the connection listener). + * If the connection has been prevented, never dispatch the open event,. + */ + if (this.readyState === this.CONNECTING) { + this.readyState = this.OPEN + this.dispatchEvent(bindEvent(this, new Event('open'))) + } + }) + } + + set onopen(listener: WebSocketEventListener | null) { + this.removeEventListener('open', this._onopen) + this._onopen = listener + if (listener !== null) { + this.addEventListener('open', listener) + } + } + get onopen(): WebSocketEventListener | null { + return this._onopen + } + + set onmessage( + listener: WebSocketEventListener> | null + ) { + this.removeEventListener( + 'message', + this._onmessage as WebSocketEventListener + ) + this._onmessage = listener + if (listener !== null) { + this.addEventListener('message', listener) + } + } + get onmessage(): WebSocketEventListener> | null { + return this._onmessage + } + + set onerror(listener: WebSocketEventListener | null) { + this.removeEventListener('error', this._onerror) + this._onerror = listener + if (listener !== null) { + this.addEventListener('error', listener) + } + } + get onerror(): WebSocketEventListener | null { + return this._onerror + } + + set onclose(listener: WebSocketEventListener | null) { + this.removeEventListener('close', this._onclose as WebSocketEventListener) + this._onclose = listener + if (listener !== null) { + this.addEventListener('close', listener) + } + } + get onclose(): WebSocketEventListener | null { + return this._onclose + } + + /** + * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0 + */ + public send(data: WebSocketData): void { + if (this.readyState === this.CONNECTING) { + this.close() + throw new DOMException('InvalidStateError') + } + + // Sending when the socket is about to close + // discards the sent data. + if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) { + return + } + + // Buffer the data to send in this even loop + // but send it in the next. + this.bufferedAmount += getDataSize(data) + + queueMicrotask(() => { + // This is a bit optimistic but since no actual data transfer + // is involved, all the data will be "sent" on the next tick. + this.bufferedAmount = 0 + + /** + * @note Notify the parent about outgoing data. + * This notifies the transport and the connection + * listens to the outgoing data to emit the "message" event. + */ + this[kOnSend]?.(data) + }) + } + + public close(code: number = 1000, reason?: string): void { + invariant(code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR) + invariant( + code === 1000 || (code >= 3000 && code <= 4999), + WEBSOCKET_CLOSE_CODE_RANGE_ERROR + ) + + this[kClose](code, reason) + } + + private [kClose]( + code: number = 1000, + reason?: string, + wasClean = true + ): void { + /** + * @note Move this check here so that even internall closures, + * like those triggered by the `server` connection, are not + * performed twice. + */ + if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) { + return + } + + this.readyState = this.CLOSING + + queueMicrotask(() => { + this.readyState = this.CLOSED + + this.dispatchEvent( + bindEvent( + this, + new CloseEvent('close', { + code, + reason, + wasClean, + }) + ) + ) + + // Remove all event listeners once the socket is closed. + this._onopen = null + this._onmessage = null + this._onerror = null + this._onclose = null + }) + } + + public addEventListener( + type: K, + listener: (this: WebSocket, event: WebSocketEventMap[K]) => void, + options?: boolean | AddEventListenerOptions + ): void + public addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions + ): void + public addEventListener( + type: unknown, + listener: unknown, + options?: unknown + ): void { + return super.addEventListener( + type as string, + listener as EventListener, + options as AddEventListenerOptions + ) + } + + removeEventListener( + type: K, + callback: EventListenerOrEventListenerObject | null, + options?: boolean | EventListenerOptions + ): void { + return super.removeEventListener(type, callback, options) + } +} + +function getDataSize(data: WebSocketData): number { + if (typeof data === 'string') { + return data.length + } + + if (data instanceof Blob) { + return data.size + } + + return data.byteLength +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketServerConnection.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketServerConnection.ts new file mode 100644 index 0000000000..dbf310cebb --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketServerConnection.ts @@ -0,0 +1,398 @@ +import { invariant } from 'outvariant' +import { + kClose, + WebSocketEventListener, + WebSocketOverride, +} from './WebSocketOverride' +import type { WebSocketData } from './WebSocketTransport' +import type { WebSocketClassTransport } from './WebSocketClassTransport' +import { bindEvent } from './utils/bindEvent' +import { + CancelableMessageEvent, + CancelableCloseEvent, + CloseEvent, +} from './utils/events' + +const kEmitter = Symbol('kEmitter') +const kBoundListener = Symbol('kBoundListener') +const kSend = Symbol('kSend') + +interface WebSocketServerEventMap { + open: Event + message: MessageEvent + error: Event + close: CloseEvent +} + +/** + * The WebSocket server instance represents the actual production + * WebSocket server connection. It's idle by default but you can + * establish it by calling `server.connect()`. + */ +export class WebSocketServerConnection { + /** + * A WebSocket instance connected to the original server. + */ + private realWebSocket?: WebSocket + private mockCloseController: AbortController + private realCloseController: AbortController + private [kEmitter]: EventTarget + + constructor( + private readonly client: WebSocketOverride, + private readonly transport: WebSocketClassTransport, + private readonly createConnection: () => WebSocket + ) { + this[kEmitter] = new EventTarget() + this.mockCloseController = new AbortController() + this.realCloseController = new AbortController() + + // Automatically forward outgoing client events + // to the actual server unless the outgoing message event + // has been prevented. The "outgoing" transport event it + // dispatched by the "client" connection. + this.transport.addEventListener('outgoing', (event) => { + // Ignore client messages if the server connection + // hasn't been established yet. Nowhere to forward. + if (typeof this.realWebSocket === 'undefined') { + return + } + + // Every outgoing client message can prevent this forwarding + // by preventing the default of the outgoing message event. + // This listener will be added before user-defined listeners, + // so execute the logic on the next tick. + queueMicrotask(() => { + if (!event.defaultPrevented) { + /** + * @note Use the internal send mechanism so consumers can tell + * apart direct user calls to `server.send()` and internal calls. + * E.g. MSW has to ignore this internal call to log out messages correctly. + */ + this[kSend](event.data) + } + }) + }) + + this.transport.addEventListener( + 'incoming', + this.handleIncomingMessage.bind(this) + ) + } + + /** + * The `WebSocket` instance connected to the original server. + * Accessing this before calling `server.connect()` will throw. + */ + public get socket(): WebSocket { + invariant( + this.realWebSocket, + 'Cannot access "socket" on the original WebSocket server object: the connection is not open. Did you forget to call `server.connect()`?' + ) + + return this.realWebSocket + } + + /** + * Open connection to the original WebSocket server. + */ + public connect(): void { + invariant( + !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN, + 'Failed to call "connect()" on the original WebSocket instance: the connection already open' + ) + + const realWebSocket = this.createConnection() + + // Inherit the binary type from the mock WebSocket client. + realWebSocket.binaryType = this.client.binaryType + + // Allow the interceptor to listen to when the server connection + // has been established. This isn't necessary to operate with the connection + // but may be beneficial in some cases (like conditionally adding logging). + realWebSocket.addEventListener( + 'open', + (event) => { + this[kEmitter].dispatchEvent( + bindEvent(this.realWebSocket!, new Event('open', event)) + ) + }, + { once: true } + ) + + realWebSocket.addEventListener('message', (event) => { + // Dispatch the "incoming" transport event instead of + // invoking the internal handler directly. This way, + // anyone can listen to the "incoming" event but this + // class is the one resulting in it. + this.transport.dispatchEvent( + bindEvent( + this.realWebSocket!, + new MessageEvent('incoming', { + data: event.data, + origin: event.origin, + }) + ) + ) + }) + + // Close the original connection when the mock client closes. + // E.g. "client.close()" was called. This is never forwarded anywhere. + this.client.addEventListener( + 'close', + (event) => { + this.handleMockClose(event) + }, + { + signal: this.mockCloseController.signal, + } + ) + + // Forward the "close" event to let the interceptor handle + // closures initiated by the original server. + realWebSocket.addEventListener( + 'close', + (event) => { + this.handleRealClose(event) + }, + { + signal: this.realCloseController.signal, + } + ) + + realWebSocket.addEventListener('error', () => { + const errorEvent = bindEvent( + realWebSocket, + new Event('error', { cancelable: true }) + ) + + // Emit the "error" event on the `server` connection + // to let the interceptor react to original server errors. + this[kEmitter].dispatchEvent(errorEvent) + + // If the error event from the original server hasn't been prevented, + // forward it to the underlying client. + if (!errorEvent.defaultPrevented) { + this.client.dispatchEvent(bindEvent(this.client, new Event('error'))) + } + }) + + this.realWebSocket = realWebSocket + } + + /** + * Listen for the incoming events from the original WebSocket server. + */ + public addEventListener( + event: EventType, + listener: WebSocketEventListener, + options?: AddEventListenerOptions | boolean + ): void { + if (!Reflect.has(listener, kBoundListener)) { + const boundListener = listener.bind(this.client) + + // Store the bound listener on the original listener + // so the exact bound function can be accessed in "removeEventListener()". + Object.defineProperty(listener, kBoundListener, { + value: boundListener, + enumerable: false, + }) + } + + this[kEmitter].addEventListener( + event, + Reflect.get(listener, kBoundListener) as EventListener, + options + ) + } + + /** + * Remove the listener for the given event. + */ + public removeEventListener( + event: EventType, + listener: WebSocketEventListener, + options?: EventListenerOptions | boolean + ): void { + this[kEmitter].removeEventListener( + event, + Reflect.get(listener, kBoundListener) as EventListener, + options + ) + } + + /** + * Send data to the original WebSocket server. + * @example + * server.send('hello') + * server.send(new Blob(['hello'])) + * server.send(new TextEncoder().encode('hello')) + */ + public send(data: WebSocketData): void { + this[kSend](data) + } + + private [kSend](data: WebSocketData): void { + const { realWebSocket } = this + + invariant( + realWebSocket, + 'Failed to call "server.send()" for "%s": the connection is not open. Did you forget to call "server.connect()"?', + this.client.url + ) + + // Silently ignore writes on the closed original WebSocket. + if ( + realWebSocket.readyState === WebSocket.CLOSING || + realWebSocket.readyState === WebSocket.CLOSED + ) { + return + } + + // Delegate the send to when the original connection is open. + // Unlike the mock, connecting to the original server may take time + // so we cannot call this on the next tick. + if (realWebSocket.readyState === WebSocket.CONNECTING) { + realWebSocket.addEventListener( + 'open', + () => { + realWebSocket.send(data) + }, + { once: true } + ) + return + } + + // Send the data to the original WebSocket server. + realWebSocket.send(data) + } + + /** + * Close the actual server connection. + */ + public close(): void { + const { realWebSocket } = this + + invariant( + realWebSocket, + 'Failed to close server connection for "%s": the connection is not open. Did you forget to call "server.connect()"?', + this.client.url + ) + + // Remove the "close" event listener from the server + // so it doesn't close the underlying WebSocket client + // when you call "server.close()". This also prevents the + // `close` event on the `server` connection from being dispatched twice. + this.realCloseController.abort() + + if ( + realWebSocket.readyState === WebSocket.CLOSING || + realWebSocket.readyState === WebSocket.CLOSED + ) { + return + } + + // Close the actual client connection. + realWebSocket.close() + + // Dispatch the "close" event on the `server` connection. + queueMicrotask(() => { + this[kEmitter].dispatchEvent( + bindEvent( + this.realWebSocket, + new CancelableCloseEvent('close', { + /** + * @note `server.close()` in the interceptor + * always results in clean closures. + */ + code: 1000, + cancelable: true, + }) + ) + ) + }) + } + + private handleIncomingMessage(event: MessageEvent): void { + // Clone the event to dispatch it on this class + // once again and prevent the "already being dispatched" + // exception. Clone it here so we can observe this event + // being prevented in the "server.on()" listeners. + const messageEvent = bindEvent( + event.target, + new CancelableMessageEvent('message', { + data: event.data, + origin: event.origin, + cancelable: true, + }) + ) + + /** + * @note Emit "message" event on the server connection + * instance to let the interceptor know about these + * incoming events from the original server. In that listener, + * the interceptor can modify or skip the event forwarding + * to the mock WebSocket instance. + */ + this[kEmitter].dispatchEvent(messageEvent) + + /** + * @note Forward the incoming server events to the client. + * Preventing the default on the message event stops this. + */ + if (!messageEvent.defaultPrevented) { + this.client.dispatchEvent( + bindEvent( + /** + * @note Bind the forwarded original server events + * to the mock WebSocket instance so it would + * dispatch them straight away. + */ + this.client, + // Clone the message event again to prevent + // the "already being dispatched" exception. + new MessageEvent('message', { + data: event.data, + origin: event.origin, + }) + ) + ) + } + } + + private handleMockClose(_event: Event): void { + // Close the original connection if the mock client closes. + if (this.realWebSocket) { + this.realWebSocket.close() + } + } + + private handleRealClose(event: CloseEvent): void { + // For closures originating from the original server, + // remove the "close" listener from the mock client. + // original close -> (?) client[kClose]() --X--> "close" (again). + this.mockCloseController.abort() + + const closeEvent = bindEvent( + this.realWebSocket, + new CancelableCloseEvent('close', { + code: event.code, + reason: event.reason, + wasClean: event.wasClean, + cancelable: true, + }) + ) + + this[kEmitter].dispatchEvent(closeEvent) + + // If the close event from the server hasn't been prevented, + // forward the closure to the mock client. + if (!closeEvent.defaultPrevented) { + // Close the intercepted client forcefully to + // allow non-configurable status codes from the server. + // If the socket has been closed by now, no harm calling + // this again—it will have no effect. + this.client[kClose](event.code, event.reason) + } + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketTransport.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketTransport.ts new file mode 100644 index 0000000000..973f511ed9 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/WebSocketTransport.ts @@ -0,0 +1,39 @@ +import { CloseEvent } from './utils/events' + +export type WebSocketData = string | ArrayBufferLike | Blob | ArrayBufferView + +export type WebSocketTransportEventMap = { + incoming: MessageEvent + outgoing: MessageEvent + close: CloseEvent +} + +export type StrictEventListenerOrEventListenerObject = + | ((this: WebSocket, event: EventType) => void) + | { + handleEvent(this: WebSocket, event: EventType): void + } + +export interface WebSocketTransport { + addEventListener( + event: EventType, + listener: StrictEventListenerOrEventListenerObject< + WebSocketTransportEventMap[EventType] + > | null, + options?: boolean | AddEventListenerOptions + ): void + + dispatchEvent( + event: WebSocketTransportEventMap[EventType] + ): boolean + + /** + * Send the data from the server to this client. + */ + send(data: WebSocketData): void + + /** + * Close the client connection. + */ + close(code?: number, reason?: string): void +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/index.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/index.ts new file mode 100644 index 0000000000..78e83dd2c1 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/index.ts @@ -0,0 +1,170 @@ +import { Interceptor } from '../../Interceptor' +import { + type WebSocketClientConnectionProtocol, + WebSocketClientConnection, +} from './WebSocketClientConnection' +import { WebSocketServerConnection } from './WebSocketServerConnection' +import { WebSocketClassTransport } from './WebSocketClassTransport' +import { + kClose, + kPassthroughPromise, + WebSocketOverride, +} from './WebSocketOverride' +import { bindEvent } from './utils/bindEvent' +import { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal' + +export { type WebSocketData, WebSocketTransport } from './WebSocketTransport' +export { + WebSocketClientConnection, + WebSocketClientConnectionProtocol, + WebSocketServerConnection, +} + +export type WebSocketEventMap = { + connection: [args: WebSocketConnectionData] +} + +export type WebSocketConnectionData = { + /** + * The incoming WebSocket client connection. + */ + client: WebSocketClientConnection + + /** + * The original WebSocket server connection. + */ + server: WebSocketServerConnection + + /** + * The connection information. + */ + info: { + /** + * The protocols supported by the WebSocket client. + */ + protocols: string | Array | undefined + } +} + +/** + * Intercept the outgoing WebSocket connections created using + * the global `WebSocket` class. + */ +export class WebSocketInterceptor extends Interceptor { + static symbol = Symbol('websocket') + + constructor() { + super(WebSocketInterceptor.symbol) + } + + protected checkEnvironment(): boolean { + return hasConfigurableGlobal('WebSocket') + } + + protected setup(): void { + const originalWebSocketDescriptor = Object.getOwnPropertyDescriptor( + globalThis, + 'WebSocket' + ) + + const WebSocketProxy = new Proxy(globalThis.WebSocket, { + construct: ( + target, + args: ConstructorParameters, + newTarget + ) => { + const [url, protocols] = args + + const createConnection = (): WebSocket => { + return Reflect.construct(target, args, newTarget) + } + + // All WebSocket instances are mocked and don't forward + // any events to the original server (no connection established). + // To forward the events, the user must use the "server.send()" API. + const socket = new WebSocketOverride(url, protocols) + const transport = new WebSocketClassTransport(socket) + + // Emit the "connection" event to the interceptor on the next tick + // so the client can modify WebSocket options, like "binaryType" + // while the connection is already pending. + queueMicrotask(() => { + try { + const server = new WebSocketServerConnection( + socket, + transport, + createConnection + ) + + // The "globalThis.WebSocket" class stands for + // the client-side connection. Assume it's established + // as soon as the WebSocket instance is constructed. + const hasConnectionListeners = this.emitter.emit('connection', { + client: new WebSocketClientConnection(socket, transport), + server, + info: { + protocols, + }, + }) + + if (hasConnectionListeners) { + socket[kPassthroughPromise].resolve(false) + } else { + socket[kPassthroughPromise].resolve(true) + + server.connect() + + // Forward the "open" event from the original server + // to the mock WebSocket client in the case of a passthrough connection. + server.addEventListener('open', () => { + socket.dispatchEvent(bindEvent(socket, new Event('open'))) + + // Forward the original connection protocol to the + // mock WebSocket client. + if (server['realWebSocket']) { + socket.protocol = server['realWebSocket'].protocol + } + }) + } + } catch (error) { + /** + * @note Translate unhandled exceptions during the connection + * handling (i.e. interceptor exceptions) as WebSocket connection + * closures with error. This prevents from the exceptions occurring + * in `queueMicrotask` from being process-wide and uncatchable. + */ + if (error instanceof Error) { + socket.dispatchEvent(new Event('error')) + + // No need to close the connection if it's already being closed. + // E.g. the interceptor called `client.close()` and then threw an error. + if ( + socket.readyState !== WebSocket.CLOSING && + socket.readyState !== WebSocket.CLOSED + ) { + socket[kClose](1011, error.message, false) + } + + console.error(error) + } + } + }) + + return socket + }, + }) + + Object.defineProperty(globalThis, 'WebSocket', { + value: WebSocketProxy, + configurable: true, + }) + + this.subscriptions.push(() => { + Object.defineProperty( + globalThis, + 'WebSocket', + originalWebSocketDescriptor! + ) + }) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/bindEvent.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/bindEvent.test.ts new file mode 100644 index 0000000000..7871961f0f --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/bindEvent.test.ts @@ -0,0 +1,27 @@ +/** + * @vitest-environment node + */ +import { it, expect } from 'vitest' +import { bindEvent } from './bindEvent' + +it('sets the "target" on the given event', () => { + class Target {} + const target = new Target() + const event = new Event('open') + bindEvent(target, event) + + expect(event.type).toBe('open') + expect(event.target).toEqual(target) +}) + +it('overrides existing "target" on the given event', () => { + class Target {} + const oldTarget = new Target() + const newTarget = new Target() + const event = new Event('open') + bindEvent(oldTarget, event) + bindEvent(newTarget, event) + + expect(event.type).toBe('open') + expect(event.target).toEqual(newTarget) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/bindEvent.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/bindEvent.ts new file mode 100644 index 0000000000..8efa682026 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/bindEvent.ts @@ -0,0 +1,21 @@ +type EventWithTarget = E & { target: T } + +export function bindEvent( + target: T, + event: E +): EventWithTarget { + Object.defineProperties(event, { + target: { + value: target, + enumerable: true, + writable: true, + }, + currentTarget: { + value: target, + enumerable: true, + writable: true, + }, + }) + + return event as EventWithTarget +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/events.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/events.test.ts new file mode 100644 index 0000000000..84a2116335 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/events.test.ts @@ -0,0 +1,101 @@ +/** + * @vitest-environment node + */ +import { describe, it, expect } from 'vitest' +import { CancelableMessageEvent, CloseEvent } from './events' + +describe(CancelableMessageEvent, () => { + it('initiates with the right defaults', () => { + const event = new CancelableMessageEvent('message', { + data: 'hello', + }) + + expect(event).toBeInstanceOf(MessageEvent) + expect(event.type).toBe('message') + expect(event.data).toBe('hello') + expect(event.cancelable).toBe(false) + expect(event.defaultPrevented).toBe(false) + }) + + it('initiates a cancelable event', () => { + const event = new CancelableMessageEvent('message', { + data: 'hello', + cancelable: true, + }) + + expect(event).toBeInstanceOf(MessageEvent) + expect(event.type).toBe('message') + expect(event.data).toBe('hello') + expect(event.cancelable).toBe(true) + expect(event.defaultPrevented).toBe(false) + }) + + it('cancels a cancelable event when calling "preventDefault()"', () => { + const event = new CancelableMessageEvent('message', { + data: 'hello', + cancelable: true, + }) + + expect(event.defaultPrevented).toBe(false) + event.preventDefault() + expect(event.defaultPrevented).toBe(true) + }) + + it('does nothing when calling "preventDefault()" on a non-cancelable event', () => { + const event = new CancelableMessageEvent('message', { + data: 'hello', + }) + + expect(event.defaultPrevented).toBe(false) + event.preventDefault() + expect(event.defaultPrevented).toBe(false) + }) + + it('supports setting the "cancelable" value directly', () => { + const event = new CancelableMessageEvent('message', {}) + /** + * @note HappyDOM sets the "cancelable" and "preventDefault" + * event properties directly. That's no-op as far as I know + * but they do it and we have to account for that. + */ + event.cancelable = true + expect(event.cancelable).toBe(true) + }) + + it('supports setting the "defaultPrevented" value directly', () => { + const event = new CancelableMessageEvent('message', {}) + /** + * @note HappyDOM sets the "cancelable" and "preventDefault" + * event properties directly. That's no-op as far as I know + * but they do it and we have to account for that. + */ + event.defaultPrevented = true + expect(event.defaultPrevented).toBe(true) + }) +}) + +describe(CloseEvent, () => { + it('initiates with the right defaults', () => { + const event = new CloseEvent('close') + + expect(event).toBeInstanceOf(Event) + expect(event.type).toBe('close') + expect(event.code).toBe(0) + expect(event.reason).toBe('') + expect(event.wasClean).toBe(false) + }) + + it('initiates with custom values', () => { + const event = new CloseEvent('close', { + code: 1003, + reason: 'close reason', + wasClean: true, + }) + + expect(event).toBeInstanceOf(Event) + expect(event.type).toBe('close') + expect(event.code).toBe(1003) + expect(event.reason).toBe('close reason') + expect(event.wasClean).toBe(true) + }) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/events.ts b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/events.ts new file mode 100644 index 0000000000..cb4c059ff6 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/WebSocket/utils/events.ts @@ -0,0 +1,94 @@ +const kCancelable = Symbol('kCancelable') +const kDefaultPrevented = Symbol('kDefaultPrevented') + +/** + * A `MessageEvent` superset that supports event cancellation + * in Node.js. It's rather non-intrusive so it can be safely + * used in the browser as well. + * + * @see https://github.com/nodejs/node/issues/51767 + */ +export class CancelableMessageEvent extends MessageEvent { + [kCancelable]: boolean; + [kDefaultPrevented]: boolean + + constructor(type: string, init: MessageEventInit) { + super(type, init) + this[kCancelable] = !!init.cancelable + this[kDefaultPrevented] = false + } + + get cancelable() { + return this[kCancelable] + } + + set cancelable(nextCancelable) { + this[kCancelable] = nextCancelable + } + + get defaultPrevented() { + return this[kDefaultPrevented] + } + + set defaultPrevented(nextDefaultPrevented) { + this[kDefaultPrevented] = nextDefaultPrevented + } + + public preventDefault(): void { + if (this.cancelable && !this[kDefaultPrevented]) { + this[kDefaultPrevented] = true + } + } +} + +interface CloseEventInit extends EventInit { + code?: number + reason?: string + wasClean?: boolean +} + +export class CloseEvent extends Event { + public code: number + public reason: string + public wasClean: boolean + + constructor(type: string, init: CloseEventInit = {}) { + super(type, init) + this.code = init.code === undefined ? 0 : init.code + this.reason = init.reason === undefined ? '' : init.reason + this.wasClean = init.wasClean === undefined ? false : init.wasClean + } +} + +export class CancelableCloseEvent extends CloseEvent { + [kCancelable]: boolean; + [kDefaultPrevented]: boolean + + constructor(type: string, init: CloseEventInit = {}) { + super(type, init) + this[kCancelable] = !!init.cancelable + this[kDefaultPrevented] = false + } + + get cancelable() { + return this[kCancelable] + } + + set cancelable(nextCancelable) { + this[kCancelable] = nextCancelable + } + + get defaultPrevented() { + return this[kDefaultPrevented] + } + + set defaultPrevented(nextDefaultPrevented) { + this[kDefaultPrevented] = nextDefaultPrevented + } + + public preventDefault(): void { + if (this.cancelable && !this[kDefaultPrevented]) { + this[kDefaultPrevented] = true + } + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts new file mode 100644 index 0000000000..9d96407c0d --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts @@ -0,0 +1,734 @@ +import { invariant } from 'outvariant' +import { isNodeProcess } from 'is-node-process' +import type { Logger } from '@open-draft/logger' +import { concatArrayBuffer } from './utils/concatArrayBuffer' +import { createEvent } from './utils/createEvent' +import { + decodeBuffer, + encodeBuffer, + toArrayBuffer, +} from '../../utils/bufferUtils' +import { createProxy } from '../../utils/createProxy' +import { isDomParserSupportedType } from './utils/isDomParserSupportedType' +import { parseJson } from '../../utils/parseJson' +import { createResponse } from './utils/createResponse' +import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor' +import { createRequestId } from '../../createRequestId' +import { getBodyByteLength } from './utils/getBodyByteLength' + +const kIsRequestHandled = Symbol('kIsRequestHandled') +const IS_NODE = isNodeProcess() +const kFetchRequest = Symbol('kFetchRequest') + +/** + * An `XMLHttpRequest` instance controller that allows us + * to handle any given request instance (e.g. responding to it). + */ +export class XMLHttpRequestController { + public request: XMLHttpRequest + public requestId: string + public onRequest?: ( + this: XMLHttpRequestController, + args: { + request: Request + requestId: string + } + ) => Promise + public onResponse?: ( + this: XMLHttpRequestController, + args: { + response: Response + isMockedResponse: boolean + request: Request + requestId: string + } + ) => void; + + [kIsRequestHandled]: boolean; + [kFetchRequest]?: Request + private method: string = 'GET' + private url: URL = null as any + private requestHeaders: Headers + private responseBuffer: Uint8Array + private events: Map> + private uploadEvents: Map< + keyof XMLHttpRequestEventTargetEventMap, + Array + > + + constructor(readonly initialRequest: XMLHttpRequest, public logger: Logger) { + this[kIsRequestHandled] = false + + this.events = new Map() + this.uploadEvents = new Map() + this.requestId = createRequestId() + this.requestHeaders = new Headers() + this.responseBuffer = new Uint8Array() + + this.request = createProxy(initialRequest, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case 'ontimeout': { + const eventName = propertyName.slice( + 2 + ) as keyof XMLHttpRequestEventTargetEventMap + + /** + * @note Proxy callbacks to event listeners because JSDOM has trouble + * translating these properties to callbacks. It seemed to be operating + * on events exclusively. + */ + this.request.addEventListener(eventName, nextValue as any) + + return invoke() + } + + default: { + return invoke() + } + } + }, + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case 'open': { + const [method, url] = args as [string, string | undefined] + + if (typeof url === 'undefined') { + this.method = 'GET' + this.url = toAbsoluteUrl(method) + } else { + this.method = method + this.url = toAbsoluteUrl(url) + } + + this.logger = this.logger.extend(`${this.method} ${this.url.href}`) + this.logger.info('open', this.method, this.url.href) + + return invoke() + } + + case 'addEventListener': { + const [eventName, listener] = args as [ + keyof XMLHttpRequestEventTargetEventMap, + Function + ] + + this.registerEvent(eventName, listener) + this.logger.info('addEventListener', eventName, listener) + + return invoke() + } + + case 'setRequestHeader': { + const [name, value] = args as [string, string] + this.requestHeaders.set(name, value) + + this.logger.info('setRequestHeader', name, value) + + return invoke() + } + + case 'send': { + const [body] = args as [ + body?: XMLHttpRequestBodyInit | Document | null + ] + + this.request.addEventListener('load', () => { + if (typeof this.onResponse !== 'undefined') { + // Create a Fetch API Response representation of whichever + // response this XMLHttpRequest received. Note those may + // be either a mocked and the original response. + const fetchResponse = createResponse( + this.request, + /** + * The `response` property is the right way to read + * the ambiguous response body, as the request's "responseType" may differ. + * @see https://xhr.spec.whatwg.org/#the-response-attribute + */ + this.request.response + ) + + // Notify the consumer about the response. + this.onResponse.call(this, { + response: fetchResponse, + isMockedResponse: this[kIsRequestHandled], + request: fetchRequest, + requestId: this.requestId!, + }) + } + }) + + const requestBody = + typeof body === 'string' ? encodeBuffer(body) : body + + // Delegate request handling to the consumer. + const fetchRequest = this.toFetchApiRequest(requestBody) + this[kFetchRequest] = fetchRequest.clone() + + const onceRequestSettled = + this.onRequest?.call(this, { + request: fetchRequest, + requestId: this.requestId!, + }) || Promise.resolve() + + onceRequestSettled.finally(() => { + // If the consumer didn't handle the request (called `.respondWith()`) perform it as-is. + if (!this[kIsRequestHandled]) { + this.logger.info( + 'request callback settled but request has not been handled (readystate %d), performing as-is...', + this.request.readyState + ) + + /** + * @note Set the intercepted request ID on the original request in Node.js + * so that if it triggers any other interceptors, they don't attempt + * to process it once again. + * + * For instance, XMLHttpRequest is often implemented via "http.ClientRequest" + * and we don't want for both XHR and ClientRequest interceptors to + * handle the same request at the same time (e.g. emit the "response" event twice). + */ + if (IS_NODE) { + this.request.setRequestHeader( + INTERNAL_REQUEST_ID_HEADER_NAME, + this.requestId! + ) + } + + return invoke() + } + }) + + break + } + + default: { + return invoke() + } + } + }, + }) + + /** + * Proxy the `.upload` property to gather the event listeners/callbacks. + */ + define( + this.request, + 'upload', + createProxy(this.request.upload, { + setProperty: ([propertyName, nextValue], invoke) => { + switch (propertyName) { + case 'onloadstart': + case 'onprogress': + case 'onaboart': + case 'onerror': + case 'onload': + case 'ontimeout': + case 'onloadend': { + const eventName = propertyName.slice( + 2 + ) as keyof XMLHttpRequestEventTargetEventMap + + this.registerUploadEvent(eventName, nextValue as Function) + } + } + + return invoke() + }, + methodCall: ([methodName, args], invoke) => { + switch (methodName) { + case 'addEventListener': { + const [eventName, listener] = args as [ + keyof XMLHttpRequestEventTargetEventMap, + Function + ] + this.registerUploadEvent(eventName, listener) + this.logger.info('upload.addEventListener', eventName, listener) + + return invoke() + } + } + }, + }) + ) + } + + private registerEvent( + eventName: keyof XMLHttpRequestEventTargetEventMap, + listener: Function + ): void { + const prevEvents = this.events.get(eventName) || [] + const nextEvents = prevEvents.concat(listener) + this.events.set(eventName, nextEvents) + + this.logger.info('registered event "%s"', eventName, listener) + } + + private registerUploadEvent( + eventName: keyof XMLHttpRequestEventTargetEventMap, + listener: Function + ): void { + const prevEvents = this.uploadEvents.get(eventName) || [] + const nextEvents = prevEvents.concat(listener) + this.uploadEvents.set(eventName, nextEvents) + + this.logger.info('registered upload event "%s"', eventName, listener) + } + + /** + * Responds to the current request with the given + * Fetch API `Response` instance. + */ + public async respondWith(response: Response): Promise { + /** + * @note Since `XMLHttpRequestController` delegates the handling of the responses + * to the "load" event listener that doesn't distinguish between the mocked and original + * responses, mark the request that had a mocked response with a corresponding symbol. + * + * Mark this request as having a mocked response immediately since + * calculating request/response total body length is asynchronous. + */ + this[kIsRequestHandled] = true + + /** + * Dispatch request upload events for requests with a body. + * @see https://github.com/mswjs/interceptors/issues/573 + */ + if (this[kFetchRequest]) { + const totalRequestBodyLength = await getBodyByteLength( + this[kFetchRequest] + ) + + this.trigger('loadstart', this.request.upload, { + loaded: 0, + total: totalRequestBodyLength, + }) + this.trigger('progress', this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength, + }) + this.trigger('load', this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength, + }) + this.trigger('loadend', this.request.upload, { + loaded: totalRequestBodyLength, + total: totalRequestBodyLength, + }) + } + + this.logger.info( + 'responding with a mocked response: %d %s', + response.status, + response.statusText + ) + + define(this.request, 'status', response.status) + define(this.request, 'statusText', response.statusText) + define(this.request, 'responseURL', this.url.href) + + this.request.getResponseHeader = new Proxy(this.request.getResponseHeader, { + apply: (_, __, args: [name: string]) => { + this.logger.info('getResponseHeader', args[0]) + + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info('headers not received yet, returning null') + + // Headers not received yet, nothing to return. + return null + } + + const headerValue = response.headers.get(args[0]) + this.logger.info( + 'resolved response header "%s" to', + args[0], + headerValue + ) + + return headerValue + }, + }) + + this.request.getAllResponseHeaders = new Proxy( + this.request.getAllResponseHeaders, + { + apply: () => { + this.logger.info('getAllResponseHeaders') + + if (this.request.readyState < this.request.HEADERS_RECEIVED) { + this.logger.info('headers not received yet, returning empty string') + + // Headers not received yet, nothing to return. + return '' + } + + const headersList = Array.from(response.headers.entries()) + const allHeaders = headersList + .map(([headerName, headerValue]) => { + return `${headerName}: ${headerValue}` + }) + .join('\r\n') + + this.logger.info('resolved all response headers to', allHeaders) + + return allHeaders + }, + } + ) + + // Update the response getters to resolve against the mocked response. + Object.defineProperties(this.request, { + response: { + enumerable: true, + configurable: false, + get: () => this.response, + }, + responseText: { + enumerable: true, + configurable: false, + get: () => this.responseText, + }, + responseXML: { + enumerable: true, + configurable: false, + get: () => this.responseXML, + }, + }) + + const totalResponseBodyLength = await getBodyByteLength(response.clone()) + + this.logger.info('calculated response body length', totalResponseBodyLength) + + this.trigger('loadstart', this.request, { + loaded: 0, + total: totalResponseBodyLength, + }) + + this.setReadyState(this.request.HEADERS_RECEIVED) + this.setReadyState(this.request.LOADING) + + const finalizeResponse = () => { + this.logger.info('finalizing the mocked response...') + + this.setReadyState(this.request.DONE) + + this.trigger('load', this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength, + }) + + this.trigger('loadend', this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength, + }) + } + + if (response.body) { + this.logger.info('mocked response has body, streaming...') + + const reader = response.body.getReader() + + const readNextResponseBodyChunk = async () => { + const { value, done } = await reader.read() + + if (done) { + this.logger.info('response body stream done!') + finalizeResponse() + return + } + + if (value) { + this.logger.info('read response body chunk:', value) + this.responseBuffer = concatArrayBuffer(this.responseBuffer, value) + + this.trigger('progress', this.request, { + loaded: this.responseBuffer.byteLength, + total: totalResponseBodyLength, + }) + } + + readNextResponseBodyChunk() + } + + readNextResponseBodyChunk() + } else { + finalizeResponse() + } + } + + private responseBufferToText(): string { + return decodeBuffer(this.responseBuffer) + } + + get response(): unknown { + this.logger.info( + 'getResponse (responseType: %s)', + this.request.responseType + ) + + if (this.request.readyState !== this.request.DONE) { + return null + } + + switch (this.request.responseType) { + case 'json': { + const responseJson = parseJson(this.responseBufferToText()) + this.logger.info('resolved response JSON', responseJson) + + return responseJson + } + + case 'arraybuffer': { + const arrayBuffer = toArrayBuffer(this.responseBuffer) + this.logger.info('resolved response ArrayBuffer', arrayBuffer) + + return arrayBuffer + } + + case 'blob': { + const mimeType = + this.request.getResponseHeader('Content-Type') || 'text/plain' + const responseBlob = new Blob([this.responseBufferToText()], { + type: mimeType, + }) + + this.logger.info( + 'resolved response Blob (mime type: %s)', + responseBlob, + mimeType + ) + + return responseBlob + } + + default: { + const responseText = this.responseBufferToText() + this.logger.info( + 'resolving "%s" response type as text', + this.request.responseType, + responseText + ) + + return responseText + } + } + } + + get responseText(): string { + /** + * Throw when trying to read the response body as text when the + * "responseType" doesn't expect text. This just respects the spec better. + * @see https://xhr.spec.whatwg.org/#the-responsetext-attribute + */ + invariant( + this.request.responseType === '' || this.request.responseType === 'text', + 'InvalidStateError: The object is in invalid state.' + ) + + if ( + this.request.readyState !== this.request.LOADING && + this.request.readyState !== this.request.DONE + ) { + return '' + } + + const responseText = this.responseBufferToText() + this.logger.info('getResponseText: "%s"', responseText) + + return responseText + } + + get responseXML(): Document | null { + invariant( + this.request.responseType === '' || + this.request.responseType === 'document', + 'InvalidStateError: The object is in invalid state.' + ) + + if (this.request.readyState !== this.request.DONE) { + return null + } + + const contentType = this.request.getResponseHeader('Content-Type') || '' + + if (typeof DOMParser === 'undefined') { + console.warn( + 'Cannot retrieve XMLHttpRequest response body as XML: DOMParser is not defined. You are likely using an environment that is not browser or does not polyfill browser globals correctly.' + ) + return null + } + + if (isDomParserSupportedType(contentType)) { + return new DOMParser().parseFromString( + this.responseBufferToText(), + contentType + ) + } + + return null + } + + public errorWith(error?: Error): void { + /** + * @note Mark this request as handled even if it received a mock error. + * This prevents the controller from trying to perform this request as-is. + */ + this[kIsRequestHandled] = true + this.logger.info('responding with an error') + + this.setReadyState(this.request.DONE) + this.trigger('error', this.request) + this.trigger('loadend', this.request) + } + + /** + * Transitions this request's `readyState` to the given one. + */ + private setReadyState(nextReadyState: number): void { + this.logger.info( + 'setReadyState: %d -> %d', + this.request.readyState, + nextReadyState + ) + + if (this.request.readyState === nextReadyState) { + this.logger.info('ready state identical, skipping transition...') + return + } + + define(this.request, 'readyState', nextReadyState) + + this.logger.info('set readyState to: %d', nextReadyState) + + if (nextReadyState !== this.request.UNSENT) { + this.logger.info('triggerring "readystatechange" event...') + + this.trigger('readystatechange', this.request) + } + } + + /** + * Triggers given event on the `XMLHttpRequest` instance. + */ + private trigger< + EventName extends keyof (XMLHttpRequestEventTargetEventMap & { + readystatechange: ProgressEvent + }) + >( + eventName: EventName, + target: XMLHttpRequest | XMLHttpRequestUpload, + options?: ProgressEventInit + ): void { + const callback = (target as XMLHttpRequest)[`on${eventName}`] + const event = createEvent(target, eventName, options) + + this.logger.info('trigger "%s"', eventName, options || '') + + // Invoke direct callbacks. + if (typeof callback === 'function') { + this.logger.info('found a direct "%s" callback, calling...', eventName) + callback.call(target as XMLHttpRequest, event) + } + + // Invoke event listeners. + const events = + target instanceof XMLHttpRequestUpload ? this.uploadEvents : this.events + + for (const [registeredEventName, listeners] of events) { + if (registeredEventName === eventName) { + this.logger.info( + 'found %d listener(s) for "%s" event, calling...', + listeners.length, + eventName + ) + + listeners.forEach((listener) => listener.call(target, event)) + } + } + } + + /** + * Converts this `XMLHttpRequest` instance into a Fetch API `Request` instance. + */ + private toFetchApiRequest( + body: XMLHttpRequestBodyInit | Document | null | undefined + ): Request { + this.logger.info('converting request to a Fetch API Request...') + + // If the `Document` is used as the body of this XMLHttpRequest, + // set its inner text as the Fetch API Request body. + const resolvedBody = + body instanceof Document ? body.documentElement.innerText : body + + const fetchRequest = new Request(this.url.href, { + method: this.method, + headers: this.requestHeaders, + /** + * @see https://xhr.spec.whatwg.org/#cross-origin-credentials + */ + credentials: this.request.withCredentials ? 'include' : 'same-origin', + body: ['GET', 'HEAD'].includes(this.method.toUpperCase()) + ? null + : resolvedBody, + }) + + const proxyHeaders = createProxy(fetchRequest.headers, { + methodCall: ([methodName, args], invoke) => { + // Forward the latest state of the internal request headers + // because the interceptor might have modified them + // without responding to the request. + switch (methodName) { + case 'append': + case 'set': { + const [headerName, headerValue] = args as [string, string] + this.request.setRequestHeader(headerName, headerValue) + break + } + + case 'delete': { + const [headerName] = args as [string] + console.warn( + `XMLHttpRequest: Cannot remove a "${headerName}" header from the Fetch API representation of the "${fetchRequest.method} ${fetchRequest.url}" request. XMLHttpRequest headers cannot be removed.` + ) + break + } + } + + return invoke() + }, + }) + define(fetchRequest, 'headers', proxyHeaders) + + this.logger.info('converted request to a Fetch API Request!', fetchRequest) + + return fetchRequest + } +} + +function toAbsoluteUrl(url: string | URL): URL { + /** + * @note XMLHttpRequest interceptor may run in environments + * that implement XMLHttpRequest but don't implement "location" + * (for example, React Native). If that's the case, return the + * input URL as-is (nothing to be relative to). + * @see https://github.com/mswjs/msw/issues/1777 + */ + if (typeof location === 'undefined') { + return new URL(url) + } + + return new URL(url.toString(), location.href) +} + +function define( + target: object, + property: string | symbol, + value: unknown +): void { + Reflect.defineProperty(target, property, { + // Ensure writable properties to allow redefining readonly properties. + writable: true, + enumerable: true, + value, + }) +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts new file mode 100644 index 0000000000..997f06fa0b --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts @@ -0,0 +1,118 @@ +import type { Logger } from '@open-draft/logger' +import { XMLHttpRequestEmitter } from '.' +import { RequestController } from '../../RequestController' +import { XMLHttpRequestController } from './XMLHttpRequestController' +import { handleRequest } from '../../utils/handleRequest' + +export interface XMLHttpRequestProxyOptions { + emitter: XMLHttpRequestEmitter + logger: Logger +} + +/** + * Create a proxied `XMLHttpRequest` class. + * The proxied class establishes spies on certain methods, + * allowing us to intercept requests and respond to them. + */ +export function createXMLHttpRequestProxy({ + emitter, + logger, +}: XMLHttpRequestProxyOptions) { + const XMLHttpRequestProxy = new Proxy(globalThis.XMLHttpRequest, { + construct(target, args, newTarget) { + logger.info('constructed new XMLHttpRequest') + + const originalRequest = Reflect.construct( + target, + args, + newTarget + ) as XMLHttpRequest + + /** + * @note Forward prototype descriptors onto the proxied object. + * XMLHttpRequest is implemented in JSDOM in a way that assigns + * a bunch of descriptors, like "set responseType()" on the prototype. + * With this propagation, we make sure that those descriptors trigger + * when the user operates with the proxied request instance. + */ + const prototypeDescriptors = Object.getOwnPropertyDescriptors( + target.prototype + ) + for (const propertyName in prototypeDescriptors) { + Reflect.defineProperty( + originalRequest, + propertyName, + prototypeDescriptors[propertyName] + ) + } + + const xhrRequestController = new XMLHttpRequestController( + originalRequest, + logger + ) + + xhrRequestController.onRequest = async function ({ request, requestId }) { + const controller = new RequestController(request) + + this.logger.info('awaiting mocked response...') + + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + emitter.listenerCount('request') + ) + + const isRequestHandled = await handleRequest({ + request, + requestId, + controller, + emitter, + onResponse: async (response) => { + await this.respondWith(response) + }, + onRequestError: () => { + this.errorWith(new TypeError('Network error')) + }, + onError: (error) => { + this.logger.info('request errored!', { error }) + + if (error instanceof Error) { + this.errorWith(error) + } + }, + }) + + if (!isRequestHandled) { + this.logger.info( + 'no mocked response received, performing request as-is...' + ) + } + } + + xhrRequestController.onResponse = async function ({ + response, + isMockedResponse, + request, + requestId, + }) { + this.logger.info( + 'emitting the "response" event for %s listener(s)...', + emitter.listenerCount('response') + ) + + emitter.emit('response', { + response, + isMockedResponse, + request, + requestId, + }) + } + + // Return the proxied request from the controller + // so that the controller can react to the consumer's interactions + // with this request (opening/sending/etc). + return xhrRequestController.request + }, + }) + + return XMLHttpRequestProxy +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/index.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/index.ts new file mode 100644 index 0000000000..6b5208c702 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/index.ts @@ -0,0 +1,61 @@ +import { invariant } from 'outvariant' +import { Emitter } from 'strict-event-emitter' +import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary' +import { Interceptor } from '../../Interceptor' +import { createXMLHttpRequestProxy } from './XMLHttpRequestProxy' +import { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal' + +export type XMLHttpRequestEmitter = Emitter + +export class XMLHttpRequestInterceptor extends Interceptor { + static interceptorSymbol = Symbol('xhr') + + constructor() { + super(XMLHttpRequestInterceptor.interceptorSymbol) + } + + protected checkEnvironment() { + return hasConfigurableGlobal('XMLHttpRequest') + } + + protected setup() { + const logger = this.logger.extend('setup') + + logger.info('patching "XMLHttpRequest" module...') + + const PureXMLHttpRequest = globalThis.XMLHttpRequest + + invariant( + !(PureXMLHttpRequest as any)[IS_PATCHED_MODULE], + 'Failed to patch the "XMLHttpRequest" module: already patched.' + ) + + globalThis.XMLHttpRequest = createXMLHttpRequestProxy({ + emitter: this.emitter, + logger: this.logger, + }) + + logger.info( + 'native "XMLHttpRequest" module patched!', + globalThis.XMLHttpRequest.name + ) + + Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true, + }) + + this.subscriptions.push(() => { + Object.defineProperty(globalThis.XMLHttpRequest, IS_PATCHED_MODULE, { + value: undefined, + }) + + globalThis.XMLHttpRequest = PureXMLHttpRequest + logger.info( + 'native "XMLHttpRequest" module restored!', + globalThis.XMLHttpRequest.name + ) + }) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts new file mode 100644 index 0000000000..4c44e50956 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/EventPolyfill.ts @@ -0,0 +1,51 @@ +export class EventPolyfill implements Event { + readonly NONE = 0 + readonly CAPTURING_PHASE = 1 + readonly AT_TARGET = 2 + readonly BUBBLING_PHASE = 3 + + public type: string = '' + public srcElement: EventTarget | null = null + public target: EventTarget | null + public currentTarget: EventTarget | null = null + public eventPhase: number = 0 + public timeStamp: number + public isTrusted: boolean = true + public composed: boolean = false + public cancelable: boolean = true + public defaultPrevented: boolean = false + public bubbles: boolean = true + public lengthComputable: boolean = true + public loaded: number = 0 + public total: number = 0 + + cancelBubble: boolean = false + returnValue: boolean = true + + constructor( + type: string, + options?: { target: EventTarget; currentTarget: EventTarget } + ) { + this.type = type + this.target = options?.target || null + this.currentTarget = options?.currentTarget || null + this.timeStamp = Date.now() + } + + public composedPath(): EventTarget[] { + return [] + } + + public initEvent(type: string, bubbles?: boolean, cancelable?: boolean) { + this.type = type + this.bubbles = !!bubbles + this.cancelable = !!cancelable + } + + public preventDefault() { + this.defaultPrevented = true + } + + public stopPropagation() {} + public stopImmediatePropagation() {} +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts new file mode 100644 index 0000000000..20a318816a --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/polyfills/ProgressEventPolyfill.ts @@ -0,0 +1,17 @@ +import { EventPolyfill } from './EventPolyfill' + +export class ProgressEventPolyfill extends EventPolyfill { + readonly lengthComputable: boolean + readonly composed: boolean + readonly loaded: number + readonly total: number + + constructor(type: string, init?: ProgressEventInit) { + super(type) + + this.lengthComputable = init?.lengthComputable || false + this.composed = init?.composed || false + this.loaded = init?.loaded || 0 + this.total = init?.total || 0 + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts new file mode 100644 index 0000000000..e8b9fb4660 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/concatArrayBuffer.ts @@ -0,0 +1,12 @@ +/** + * Concatenate two `Uint8Array` buffers. + */ +export function concatArrayBuffer( + left: Uint8Array, + right: Uint8Array +): Uint8Array { + const result = new Uint8Array(left.byteLength + right.byteLength) + result.set(left, 0) + result.set(right, left.byteLength) + return result +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts new file mode 100644 index 0000000000..fab59abd62 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/concateArrayBuffer.test.ts @@ -0,0 +1,12 @@ +import { it, expect } from 'vitest' +import { concatArrayBuffer } from './concatArrayBuffer' + +const encoder = new TextEncoder() + +it('concatenates two Uint8Array buffers', () => { + const result = concatArrayBuffer( + encoder.encode('hello'), + encoder.encode('world') + ) + expect(result).toEqual(encoder.encode('helloworld')) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts new file mode 100644 index 0000000000..0b23216913 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createEvent.test.ts @@ -0,0 +1,26 @@ +// @vitest-environment jsdom +import { it, expect } from 'vitest' +import { createEvent } from './createEvent' +import { EventPolyfill } from '../polyfills/EventPolyfill' + +const request = new XMLHttpRequest() +request.open('POST', '/user') + +it('returns an EventPolyfill instance with the given target set', () => { + const event = createEvent(request, 'my-event') + const target = event.target as XMLHttpRequest + + expect(event).toBeInstanceOf(EventPolyfill) + expect(target).toBeInstanceOf(XMLHttpRequest) +}) + +it('returns the ProgressEvent instance', () => { + const event = createEvent(request, 'load', { + loaded: 100, + total: 500, + }) + + expect(event).toBeInstanceOf(ProgressEvent) + expect(event.loaded).toBe(100) + expect(event.total).toBe(500) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createEvent.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createEvent.ts new file mode 100644 index 0000000000..be87b36927 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createEvent.ts @@ -0,0 +1,41 @@ +import { EventPolyfill } from '../polyfills/EventPolyfill' +import { ProgressEventPolyfill } from '../polyfills/ProgressEventPolyfill' + +const SUPPORTS_PROGRESS_EVENT = typeof ProgressEvent !== 'undefined' + +export function createEvent( + target: XMLHttpRequest | XMLHttpRequestUpload, + type: string, + init?: ProgressEventInit +): EventPolyfill | ProgressEvent { + const progressEvents = [ + 'error', + 'progress', + 'loadstart', + 'loadend', + 'load', + 'timeout', + 'abort', + ] + + /** + * `ProgressEvent` is not supported in React Native. + * @see https://github.com/mswjs/interceptors/issues/40 + */ + const ProgressEventClass = SUPPORTS_PROGRESS_EVENT + ? ProgressEvent + : ProgressEventPolyfill + + const event = progressEvents.includes(type) + ? new ProgressEventClass(type, { + lengthComputable: true, + loaded: init?.loaded || 0, + total: init?.total || 0, + }) + : new EventPolyfill(type, { + target, + currentTarget: target, + }) + + return event +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createResponse.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createResponse.ts new file mode 100644 index 0000000000..d0e8d1d868 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/createResponse.ts @@ -0,0 +1,49 @@ +import { FetchResponse } from '../../../utils/fetchUtils' + +/** + * Creates a Fetch API `Response` instance from the given + * `XMLHttpRequest` instance and a response body. + */ +export function createResponse( + request: XMLHttpRequest, + body: BodyInit | null +): Response { + /** + * Handle XMLHttpRequest responses that must have null as the + * response body when represented using Fetch API Response. + * XMLHttpRequest response will always have an empty string + * as the "request.response" in those cases, resulting in an error + * when constructing a Response instance. + * @see https://github.com/mswjs/interceptors/issues/379 + */ + const responseBodyOrNull = FetchResponse.isResponseWithBody(request.status) + ? body + : null + + return new FetchResponse(responseBodyOrNull, { + url: request.responseURL, + status: request.status, + statusText: request.statusText, + headers: createHeadersFromXMLHttpReqestHeaders( + request.getAllResponseHeaders() + ), + }) +} + +function createHeadersFromXMLHttpReqestHeaders(headersString: string): Headers { + const headers = new Headers() + + const lines = headersString.split(/[\r\n]+/) + for (const line of lines) { + if (line.trim() === '') { + continue + } + + const [name, ...parts] = line.split(': ') + const value = parts.join(': ') + + headers.append(name, value) + } + + return headers +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts new file mode 100644 index 0000000000..f2a41c8e8c --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.test.ts @@ -0,0 +1,164 @@ +// @vitest-environment node +import { it, expect } from 'vitest' +import { getBodyByteLength } from './getBodyByteLength' + +const url = 'http://localhost' + +it('returns explicit body length set in the "Content-Length" header', async () => { + await expect( + getBodyByteLength(new Request(url, { headers: { 'Content-Length': '10' } })) + ).resolves.toBe(10) + + await expect( + getBodyByteLength( + new Response('hello', { headers: { 'Content-Length': '5' } }) + ) + ).resolves.toBe(5) +}) + +/** + * Request. + */ + +it('returns 0 for a request with an empty body', async () => { + await expect(getBodyByteLength(new Request(url))).resolves.toBe(0) + await expect( + getBodyByteLength(new Request(url, { method: 'POST', body: null })) + ).resolves.toBe(0) + await expect( + getBodyByteLength(new Request(url, { method: 'POST', body: undefined })) + ).resolves.toBe(0) + await expect( + getBodyByteLength(new Request(url, { method: 'POST', body: '' })) + ).resolves.toBe(0) +}) + +it('calculates body length from the text request body', async () => { + await expect( + getBodyByteLength( + new Request(url, { + method: 'POST', + body: 'hello world', + }) + ) + ).resolves.toBe(11) +}) + +it('calculates body length from the URLSearchParams request body', async () => { + await expect( + getBodyByteLength( + new Request(url, { + method: 'POST', + body: new URLSearchParams([['hello', 'world']]), + }) + ) + ).resolves.toBe(11) +}) + +it('calculates body length from the Blob request body', async () => { + await expect( + getBodyByteLength( + new Request(url, { + method: 'POST', + body: new Blob(['hello world']), + }) + ) + ).resolves.toBe(11) +}) + +it('calculates body length from the ArrayBuffer request body', async () => { + await expect( + getBodyByteLength( + new Request(url, { + method: 'POST', + body: await new Blob(['hello world']).arrayBuffer(), + }) + ) + ).resolves.toBe(11) +}) + +it('calculates body length from the FormData request body', async () => { + const formData = new FormData() + formData.append('hello', 'world') + + await expect( + getBodyByteLength( + new Request(url, { + method: 'POST', + body: formData, + }) + ) + ).resolves.toBe(127) +}) + +it('calculates body length from the ReadableStream request body', async () => { + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(new TextEncoder().encode('hello world')) + controller.close() + }, + }) + + await expect( + getBodyByteLength( + new Request(url, { + method: 'POST', + body: stream, + // @ts-expect-error Undocumented required Undici property. + duplex: 'half', + }) + ) + ).resolves.toBe(11) +}) + +/** + * Response. + */ +it('returns 0 for a response with an empty body', async () => { + await expect(getBodyByteLength(new Response())).resolves.toBe(0) + await expect(getBodyByteLength(new Response(null))).resolves.toBe(0) + await expect(getBodyByteLength(new Response(undefined))).resolves.toBe(0) + await expect(getBodyByteLength(new Response(''))).resolves.toBe(0) +}) + +it('calculates body length from the text response body', async () => { + await expect(getBodyByteLength(new Response('hello world'))).resolves.toBe(11) +}) + +it('calculates body length from the URLSearchParams response body', async () => { + await expect( + getBodyByteLength(new Response(new URLSearchParams([['hello', 'world']]))) + ).resolves.toBe(11) +}) + +it('calculates body length from the Blob response body', async () => { + await expect( + getBodyByteLength(new Response(new Blob(['hello world']))) + ).resolves.toBe(11) +}) + +it('calculates body length from the ArrayBuffer response body', async () => { + await expect( + getBodyByteLength( + new Response(await new Blob(['hello world']).arrayBuffer()) + ) + ).resolves.toBe(11) +}) + +it('calculates body length from the FormData response body', async () => { + const formData = new FormData() + formData.append('hello', 'world') + + await expect(getBodyByteLength(new Response(formData))).resolves.toBe(127) +}) + +it('calculates body length from the ReadableStream response body', async () => { + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(new TextEncoder().encode('hello world')) + controller.close() + }, + }) + + await expect(getBodyByteLength(new Response(stream))).resolves.toBe(11) +}) diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts new file mode 100644 index 0000000000..dd7655ab0c --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/getBodyByteLength.ts @@ -0,0 +1,16 @@ +/** + * Return a total byte length of the given request/response body. + * If the `Content-Length` header is present, it will be used as the byte length. + */ +export async function getBodyByteLength( + input: Request | Response +): Promise { + const explicitContentLength = input.headers.get('content-length') + + if (explicitContentLength != null && explicitContentLength !== '') { + return Number(explicitContentLength) + } + + const buffer = await input.arrayBuffer() + return buffer.byteLength +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts new file mode 100644 index 0000000000..3cf18b0400 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/utils/isDomParserSupportedType.ts @@ -0,0 +1,14 @@ +export function isDomParserSupportedType( + type: string +): type is DOMParserSupportedType { + const supportedTypes: Array = [ + 'application/xhtml+xml', + 'application/xml', + 'image/svg+xml', + 'text/html', + 'text/xml', + ] + return supportedTypes.some((supportedType) => { + return type.startsWith(supportedType) + }) +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts b/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts new file mode 100644 index 0000000000..d134fc1611 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/fetch/index.ts @@ -0,0 +1,186 @@ +import { invariant } from 'outvariant' +import { DeferredPromise } from '@open-draft/deferred-promise' +import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary' +import { Interceptor } from '../../Interceptor' +import { RequestController } from '../../RequestController' +import { emitAsync } from '../../utils/emitAsync' +import { handleRequest } from '../../utils/handleRequest' +import { canParseUrl } from '../../utils/canParseUrl' +import { createRequestId } from '../../createRequestId' +import { createNetworkError } from './utils/createNetworkError' +import { followFetchRedirect } from './utils/followRedirect' +import { decompressResponse } from './utils/decompression' +import { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal' +import { FetchResponse } from '../../utils/fetchUtils' + +export class FetchInterceptor extends Interceptor { + static symbol = Symbol('fetch') + + constructor() { + super(FetchInterceptor.symbol) + } + + protected checkEnvironment() { + return hasConfigurableGlobal('fetch') + } + + protected async setup() { + const pureFetch = globalThis.fetch + + invariant( + !(pureFetch as any)[IS_PATCHED_MODULE], + 'Failed to patch the "fetch" module: already patched.' + ) + + globalThis.fetch = async (input, init) => { + const requestId = createRequestId() + + /** + * @note Resolve potentially relative request URL + * against the present `location`. This is mainly + * for native `fetch` in JSDOM. + * @see https://github.com/mswjs/msw/issues/1625 + */ + const resolvedInput = + typeof input === 'string' && + typeof location !== 'undefined' && + !canParseUrl(input) + ? new URL(input, location.origin) + : input + + const request = new Request(resolvedInput, init) + const responsePromise = new DeferredPromise() + const controller = new RequestController(request) + + this.logger.info('[%s] %s', request.method, request.url) + this.logger.info('awaiting for the mocked response...') + + this.logger.info( + 'emitting the "request" event for %s listener(s)...', + this.emitter.listenerCount('request') + ) + + const isRequestHandled = await handleRequest({ + request, + requestId, + emitter: this.emitter, + controller, + onResponse: async (rawResponse) => { + this.logger.info('received mocked response!', { + rawResponse, + }) + + // Decompress the mocked response body, if applicable. + const decompressedStream = decompressResponse(rawResponse) + const response = + decompressedStream === null + ? rawResponse + : new FetchResponse(decompressedStream, rawResponse) + + FetchResponse.setUrl(request.url, response) + + /** + * Undici's handling of following redirect responses. + * Treat the "manual" redirect mode as a regular mocked response. + * This way, the client can manually follow the redirect it receives. + * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173 + */ + if (FetchResponse.isRedirectResponse(response.status)) { + // Reject the request promise if its `redirect` is set to `error` + // and it receives a mocked redirect response. + if (request.redirect === 'error') { + responsePromise.reject(createNetworkError('unexpected redirect')) + return + } + + if (request.redirect === 'follow') { + followFetchRedirect(request, response).then( + (response) => { + responsePromise.resolve(response) + }, + (reason) => { + responsePromise.reject(reason) + } + ) + return + } + } + + if (this.emitter.listenerCount('response') > 0) { + this.logger.info('emitting the "response" event...') + + // Await the response listeners to finish before resolving + // the response promise. This ensures all your logic finishes + // before the interceptor resolves the pending response. + await emitAsync(this.emitter, 'response', { + // Clone the mocked response for the "response" event listener. + // This way, the listener can read the response and not lock its body + // for the actual fetch consumer. + response: response.clone(), + isMockedResponse: true, + request, + requestId, + }) + } + + responsePromise.resolve(response) + }, + onRequestError: (response) => { + this.logger.info('request has errored!', { response }) + responsePromise.reject(createNetworkError(response)) + }, + onError: (error) => { + this.logger.info('request has been aborted!', { error }) + responsePromise.reject(error) + }, + }) + + if (isRequestHandled) { + this.logger.info('request has been handled, returning mock promise...') + return responsePromise + } + + this.logger.info( + 'no mocked response received, performing request as-is...' + ) + + return pureFetch(request).then(async (response) => { + this.logger.info('original fetch performed', response) + + if (this.emitter.listenerCount('response') > 0) { + this.logger.info('emitting the "response" event...') + + const responseClone = response.clone() + + await emitAsync(this.emitter, 'response', { + response: responseClone, + isMockedResponse: false, + request, + requestId, + }) + } + + return response + }) + } + + Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, { + enumerable: true, + configurable: true, + value: true, + }) + + this.subscriptions.push(() => { + Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, { + value: undefined, + }) + + globalThis.fetch = pureFetch + + this.logger.info( + 'restored native "globalThis.fetch"!', + globalThis.fetch.name + ) + }) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/brotli-decompress.browser.ts b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/brotli-decompress.browser.ts new file mode 100644 index 0000000000..d88ca784f9 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/brotli-decompress.browser.ts @@ -0,0 +1,14 @@ +export class BrotliDecompressionStream extends TransformStream { + constructor() { + console.warn( + '[Interceptors]: Brotli decompression of response streams is not supported in the browser' + ) + + super({ + transform(chunk, controller) { + // Keep the stream as passthrough, it does nothing. + controller.enqueue(chunk) + }, + }) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/brotli-decompress.ts b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/brotli-decompress.ts new file mode 100644 index 0000000000..dbfa622e59 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/brotli-decompress.ts @@ -0,0 +1,31 @@ +import zlib from 'node:zlib' + +export class BrotliDecompressionStream extends TransformStream { + constructor() { + const decompress = zlib.createBrotliDecompress({ + flush: zlib.constants.BROTLI_OPERATION_FLUSH, + finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH, + }) + + super({ + async transform(chunk, controller) { + const buffer = Buffer.from(chunk) + + const decompressed = await new Promise((resolve, reject) => { + decompress.write(buffer, (error) => { + if (error) reject(error) + }) + + decompress.flush() + decompress.once('data', (data) => resolve(data)) + decompress.once('error', (error) => reject(error)) + decompress.once('end', () => controller.terminate()) + }).catch((error) => { + controller.error(error) + }) + + controller.enqueue(decompressed) + }, + }) + } +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/createNetworkError.ts b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/createNetworkError.ts new file mode 100644 index 0000000000..bf58f07080 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/createNetworkError.ts @@ -0,0 +1,5 @@ +export function createNetworkError(cause?: unknown) { + return Object.assign(new TypeError('Failed to fetch'), { + cause, + }) +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/decompression.ts b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/decompression.ts new file mode 100644 index 0000000000..583d4a37ed --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/decompression.ts @@ -0,0 +1,85 @@ +// Import from an internal alias that resolves to different modules +// depending on the environment. This way, we can keep the fetch interceptor +// intact while using different strategies for Brotli decompression. +import { BrotliDecompressionStream } from 'internal:brotli-decompress' + +class PipelineStream extends TransformStream { + constructor( + transformStreams: Array, + ...strategies: Array + ) { + super({}, ...strategies) + + const readable = [super.readable as any, ...transformStreams].reduce( + (readable, transform) => readable.pipeThrough(transform) + ) + + Object.defineProperty(this, 'readable', { + get() { + return readable + }, + }) + } +} + +export function parseContentEncoding(contentEncoding: string): Array { + return contentEncoding + .toLowerCase() + .split(',') + .map((coding) => coding.trim()) +} + +function createDecompressionStream( + contentEncoding: string +): TransformStream | null { + if (contentEncoding === '') { + return null + } + + const codings = parseContentEncoding(contentEncoding) + + if (codings.length === 0) { + return null + } + + const transformers = codings.reduceRight>( + (transformers, coding) => { + if (coding === 'gzip' || coding === 'x-gzip') { + return transformers.concat(new DecompressionStream('gzip')) + } else if (coding === 'deflate') { + return transformers.concat(new DecompressionStream('deflate')) + } else if (coding === 'br') { + return transformers.concat(new BrotliDecompressionStream()) + } else { + transformers.length = 0 + } + + return transformers + }, + [] + ) + + return new PipelineStream(transformers) +} + +export function decompressResponse( + response: Response +): ReadableStream | null { + if (response.body === null) { + return null + } + + const decompressionStream = createDecompressionStream( + response.headers.get('content-encoding') || '' + ) + + if (!decompressionStream) { + return null + } + + // Use `pipeTo` and return the decompression stream's readable + // instead of `pipeThrough` because that will lock the original + // response stream, making it unusable as the input to Response. + response.body.pipeTo(decompressionStream.writable) + return decompressionStream.readable +} diff --git a/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/followRedirect.ts b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/followRedirect.ts new file mode 100644 index 0000000000..bd76e63b70 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/interceptors/fetch/utils/followRedirect.ts @@ -0,0 +1,108 @@ +import { createNetworkError } from './createNetworkError' + +const REQUEST_BODY_HEADERS = [ + 'content-encoding', + 'content-language', + 'content-location', + 'content-type', + 'content-length', +] + +const kRedirectCount = Symbol('kRedirectCount') + +/** + * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1210 + */ +export async function followFetchRedirect( + request: Request, + response: Response +): Promise { + if (response.status !== 303 && request.body != null) { + return Promise.reject(createNetworkError()) + } + + const requestUrl = new URL(request.url) + + let locationUrl: URL + try { + // If the location is a relative URL, use the request URL as the base URL. + locationUrl = new URL(response.headers.get('location')!, request.url) + } catch (error) { + return Promise.reject(createNetworkError(error)) + } + + if ( + !(locationUrl.protocol === 'http:' || locationUrl.protocol === 'https:') + ) { + return Promise.reject( + createNetworkError('URL scheme must be a HTTP(S) scheme') + ) + } + + if (Reflect.get(request, kRedirectCount) > 20) { + return Promise.reject(createNetworkError('redirect count exceeded')) + } + + Object.defineProperty(request, kRedirectCount, { + value: (Reflect.get(request, kRedirectCount) || 0) + 1, + }) + + if ( + request.mode === 'cors' && + (locationUrl.username || locationUrl.password) && + !sameOrigin(requestUrl, locationUrl) + ) { + return Promise.reject( + createNetworkError('cross origin not allowed for request mode "cors"') + ) + } + + const requestInit: RequestInit = {} + + if ( + ([301, 302].includes(response.status) && request.method === 'POST') || + (response.status === 303 && !['HEAD', 'GET'].includes(request.method)) + ) { + requestInit.method = 'GET' + requestInit.body = null + + REQUEST_BODY_HEADERS.forEach((headerName) => { + request.headers.delete(headerName) + }) + } + + if (!sameOrigin(requestUrl, locationUrl)) { + request.headers.delete('authorization') + request.headers.delete('proxy-authorization') + request.headers.delete('cookie') + request.headers.delete('host') + } + + /** + * @note Undici "safely" extracts the request body. + * I suspect we cannot dispatch this request again + * since its body has been read and the stream is locked. + */ + + requestInit.headers = request.headers + return fetch(new Request(locationUrl, requestInit)) +} + +/** + * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/util.js#L761 + */ +function sameOrigin(left: URL, right: URL): boolean { + if (left.origin === right.origin && left.origin === 'null') { + return true + } + + if ( + left.protocol === right.protocol && + left.hostname === right.hostname && + left.port === right.port + ) { + return true + } + + return false +} diff --git a/node_modules/@mswjs/interceptors/src/presets/browser.ts b/node_modules/@mswjs/interceptors/src/presets/browser.ts new file mode 100644 index 0000000000..c609adc5e7 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/presets/browser.ts @@ -0,0 +1,11 @@ +import { FetchInterceptor } from '../interceptors/fetch' +import { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest' + +/** + * The default preset provisions the interception of requests + * regardless of their type (fetch/XMLHttpRequest). + */ +export default [ + new FetchInterceptor(), + new XMLHttpRequestInterceptor(), +] as const diff --git a/node_modules/@mswjs/interceptors/src/presets/node.ts b/node_modules/@mswjs/interceptors/src/presets/node.ts new file mode 100644 index 0000000000..63fbe0f459 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/presets/node.ts @@ -0,0 +1,13 @@ +import { ClientRequestInterceptor } from '../interceptors/ClientRequest' +import { XMLHttpRequestInterceptor } from '../interceptors/XMLHttpRequest' +import { FetchInterceptor } from '../interceptors/fetch' + +/** + * The default preset provisions the interception of requests + * regardless of their type (http/https/XMLHttpRequest). + */ +export default [ + new ClientRequestInterceptor(), + new XMLHttpRequestInterceptor(), + new FetchInterceptor(), +] as const diff --git a/node_modules/@mswjs/interceptors/src/utils/RequestController.ts b/node_modules/@mswjs/interceptors/src/utils/RequestController.ts new file mode 100644 index 0000000000..d93e70b3d5 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/RequestController.ts @@ -0,0 +1,21 @@ +import { invariant } from 'outvariant' +import { DeferredPromise } from '@open-draft/deferred-promise' + +export class RequestController { + public responsePromise: DeferredPromise + + constructor(protected request: Request) { + this.responsePromise = new DeferredPromise() + } + + public respondWith(response?: Response): void { + invariant( + this.responsePromise.state === 'pending', + 'Failed to respond to "%s %s" request: the "request" event has already been responded to.', + this.request.method, + this.request.url + ) + + this.responsePromise.resolve(response) + } +} diff --git a/node_modules/@mswjs/interceptors/src/utils/bufferUtils.test.ts b/node_modules/@mswjs/interceptors/src/utils/bufferUtils.test.ts new file mode 100644 index 0000000000..7c55455616 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/bufferUtils.test.ts @@ -0,0 +1,21 @@ +import { it, expect } from 'vitest' +import { decodeBuffer, encodeBuffer } from './bufferUtils' + +it('encodes utf-8 string', () => { + const encoded = encodeBuffer('😁') + expect(new Uint8Array(encoded)).toEqual(new Uint8Array([240, 159, 152, 129])) +}) + +it('decodes utf-8 string', () => { + const array = new Uint8Array([240, 159, 152, 129]) + const decoded = decodeBuffer(array.buffer) + expect(decoded).toEqual('😁') +}) + +it('decodes string with custom encoding', () => { + const array = new Uint8Array([ + 207, 240, 232, 226, 229, 242, 44, 32, 236, 232, 240, 33, + ]) + const decoded = decodeBuffer(array.buffer, 'windows-1251') + expect(decoded).toEqual('Привет, мир!') +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/bufferUtils.ts b/node_modules/@mswjs/interceptors/src/utils/bufferUtils.ts new file mode 100644 index 0000000000..b4b1c3784d --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/bufferUtils.ts @@ -0,0 +1,22 @@ +const encoder = new TextEncoder() + +export function encodeBuffer(text: string): Uint8Array { + return encoder.encode(text) +} + +export function decodeBuffer(buffer: ArrayBuffer, encoding?: string): string { + const decoder = new TextDecoder(encoding) + return decoder.decode(buffer) +} + +/** + * Create an `ArrayBuffer` from the given `Uint8Array`. + * Takes the byte offset into account to produce the right buffer + * in the case when the buffer is bigger than the data view. + */ +export function toArrayBuffer(array: Uint8Array): ArrayBuffer { + return array.buffer.slice( + array.byteOffset, + array.byteOffset + array.byteLength + ) +} diff --git a/node_modules/@mswjs/interceptors/src/utils/canParseUrl.ts b/node_modules/@mswjs/interceptors/src/utils/canParseUrl.ts new file mode 100644 index 0000000000..7f814cd526 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/canParseUrl.ts @@ -0,0 +1,13 @@ +/** + * Returns a boolean indicating whether the given URL string + * can be parsed into a `URL` instance. + * A substitute for `URL.canParse()` for Node.js 18. + */ +export function canParseUrl(url: string): boolean { + try { + new URL(url) + return true + } catch (_error) { + return false + } +} diff --git a/node_modules/@mswjs/interceptors/src/utils/cloneObject.test.ts b/node_modules/@mswjs/interceptors/src/utils/cloneObject.test.ts new file mode 100644 index 0000000000..85a1dbbb3f --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/cloneObject.test.ts @@ -0,0 +1,94 @@ +import { it, expect } from 'vitest' +import { cloneObject } from './cloneObject' + +it('clones a shallow object', () => { + const original = { a: 1, b: 2, c: [1, 2, 3] } + const clone = cloneObject(original) + + expect(clone).toEqual(original) + + clone.a = 5 + clone.b = 6 + clone.c = [5, 6, 7] + + expect(clone).toHaveProperty('a', 5) + expect(clone).toHaveProperty('b', 6) + expect(clone).toHaveProperty('c', [5, 6, 7]) + expect(original).toHaveProperty('a', 1) + expect(original).toHaveProperty('b', 2) + expect(original).toHaveProperty('c', [1, 2, 3]) +}) + +it('clones a nested object', () => { + const original = { a: { b: 1 }, c: { d: { e: 2 } } } + const clone = cloneObject(original) + + expect(clone).toEqual(original) + + clone.a.b = 10 + clone.c.d.e = 20 + + expect(clone).toHaveProperty(['a', 'b'], 10) + expect(clone).toHaveProperty(['c', 'd', 'e'], 20) + expect(original).toHaveProperty(['a', 'b'], 1) + expect(original).toHaveProperty(['c', 'd', 'e'], 2) +}) + +it('clones a class instance', () => { + class Car { + public manufacturer: string + constructor() { + this.manufacturer = 'Audi' + } + getManufacturer() { + return this.manufacturer + } + } + + const car = new Car() + const clone = cloneObject(car) + + expect(clone).toHaveProperty('manufacturer', 'Audi') + expect(clone).toHaveProperty('getManufacturer') + expect(clone.getManufacturer).toBeInstanceOf(Function) + expect(clone.getManufacturer()).toEqual('Audi') +}) + +it('ignores nested class instances', () => { + class Car { + name: string + constructor(name: string) { + this.name = name + } + getName() { + return this.name + } + } + const original = { + a: 1, + car: new Car('Audi'), + } + const clone = cloneObject(original) + + expect(clone).toEqual(original) + expect(clone.car).toBeInstanceOf(Car) + expect(clone.car.getName()).toEqual('Audi') + + clone.car = new Car('BMW') + + expect(clone.car).toBeInstanceOf(Car) + expect(clone.car.getName()).toEqual('BMW') + expect(original.car).toBeInstanceOf(Car) + expect(original.car.getName()).toEqual('Audi') +}) + +it('clones an object with null prototype', () => { + const original = { + key: Object.create(null), + } + const clone = cloneObject(original) + + expect(clone).toEqual({ + key: {}, + }) +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/cloneObject.ts b/node_modules/@mswjs/interceptors/src/utils/cloneObject.ts new file mode 100644 index 0000000000..521f2ea003 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/cloneObject.ts @@ -0,0 +1,36 @@ +import { Logger } from '@open-draft/logger' + +const logger = new Logger('cloneObject') + +function isPlainObject(obj?: Record): boolean { + logger.info('is plain object?', obj) + + if (obj == null || !obj.constructor?.name) { + logger.info('given object is undefined, not a plain object...') + return false + } + + logger.info('checking the object constructor:', obj.constructor.name) + return obj.constructor.name === 'Object' +} + +export function cloneObject>( + obj: ObjectType +): ObjectType { + logger.info('cloning object:', obj) + + const enumerableProperties = Object.entries(obj).reduce>( + (acc, [key, value]) => { + logger.info('analyzing key-value pair:', key, value) + + // Recursively clone only plain objects, omitting class instances. + acc[key] = isPlainObject(value) ? cloneObject(value) : value + return acc + }, + {} + ) + + return isPlainObject(obj) + ? enumerableProperties + : Object.assign(Object.getPrototypeOf(obj), enumerableProperties) +} diff --git a/node_modules/@mswjs/interceptors/src/utils/createProxy.test.ts b/node_modules/@mswjs/interceptors/src/utils/createProxy.test.ts new file mode 100644 index 0000000000..0688aacc3b --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/createProxy.test.ts @@ -0,0 +1,162 @@ +import { vi, it, expect } from 'vitest' +import { createProxy } from './createProxy' + +it('does not interfere with default constructors', () => { + const ProxyClass = createProxy( + class { + constructor(public name: string) {} + }, + {} + ) + + const instance = new ProxyClass('John') + expect(instance.name).toBe('John') +}) + +it('does not interfere with default getters', () => { + const proxy = createProxy({ foo: 'initial' }, {}) + expect(proxy.foo).toBe('initial') +}) + +it('does not interfere with default setters', () => { + const proxy = createProxy({ foo: 'initial' }, {}) + proxy.foo = 'next' + + expect(proxy.foo).toBe('next') +}) + +it('does not interfere with default methods', () => { + const proxy = createProxy({ getValue: () => 'initial' }, {}) + expect(proxy.getValue()).toBe('initial') +}) + +it('does not interfere with existing descriptors', () => { + const target = {} as { foo: string; bar: number } + let internalBar = 0 + + Object.defineProperties(target, { + foo: { + get: () => 'initial', + }, + bar: { + set: (value) => { + internalBar = value + 10 + }, + }, + }) + + const proxy = createProxy(target, { + getProperty(data, next) { + return next() + }, + }) + expect(proxy.foo).toBe('initial') + + proxy.bar = 5 + expect(proxy.bar).toBeUndefined() + expect(internalBar).toBe(15) +}) + +it('infer prototype descriptors', () => { + class Child { + ok: boolean + + set status(nextStatus: number) { + this.ok = nextStatus >= 200 && nextStatus < 300 + } + } + + Object.defineProperties(Child.prototype, { + status: { enumerable: true }, + }) + + const scope = {} as { child: typeof Child } + + Object.defineProperty(scope, 'child', { + enumerable: true, + value: Child, + }) + + const ProxyClass = createProxy(scope.child, {}) + const instance = new ProxyClass() + + instance.status = 201 + expect(instance.ok).toBe(true) +}) + +it('spies on the constructor', () => { + const OriginalClass = class { + constructor(public name: string, public age: number) {} + } + + const constructorCall = vi.fn< + [ConstructorParameters, Function], + typeof OriginalClass + >((args, next) => next()) + + const ProxyClass = createProxy(OriginalClass, { + constructorCall, + }) + + new ProxyClass('John', 32) + + expect(constructorCall).toHaveBeenCalledTimes(1) + expect(constructorCall).toHaveBeenCalledWith( + ['John', 32], + expect.any(Function) + ) +}) + +it('spies on property getters', () => { + const getProperty = vi.fn((args, next) => next()) + const proxy = createProxy({ foo: 'initial' }, { getProperty }) + + proxy.foo + + expect(getProperty).toHaveBeenCalledTimes(1) + expect(getProperty).toHaveBeenCalledWith(['foo', proxy], expect.any(Function)) +}) + +it('spies on property setters', () => { + const setProperty = vi.fn((args, next) => next()) + const proxy = createProxy({ foo: 'initial' }, { setProperty }) + + proxy.foo = 'next' + + expect(setProperty).toHaveBeenCalledTimes(1) + expect(setProperty).toHaveBeenCalledWith( + ['foo', 'next'], + expect.any(Function) + ) +}) + +it('spies on method calls', () => { + const methodCall = vi.fn((args, next) => next()) + const proxy = createProxy( + { + greet: (name: string) => `hello ${name}`, + }, + { methodCall } + ) + + proxy.greet('Clair') + + expect(methodCall).toHaveBeenCalledTimes(1) + expect(methodCall).toHaveBeenCalledWith( + ['greet', ['Clair']], + expect.any(Function) + ) +}) + +it('proxies properties on the prototype level', () => { + const method = vi.fn() + const prototype = { method } + + const proxy = createProxy(Object.create(prototype), {}) + const proxyMethod = vi.fn() + proxy.method = proxyMethod + + prototype.method() + expect(method).toHaveBeenCalledTimes(0) + expect(proxyMethod).toHaveBeenCalledTimes(1) +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/createProxy.ts b/node_modules/@mswjs/interceptors/src/utils/createProxy.ts new file mode 100644 index 0000000000..054e752437 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/createProxy.ts @@ -0,0 +1,104 @@ +import { findPropertySource } from './findPropertySource' + +export interface ProxyOptions> { + constructorCall?(args: Array, next: NextFunction): Target + + methodCall?( + this: Target, + data: [methodName: F, args: Array], + next: NextFunction + ): void + + setProperty?( + data: [propertyName: string | symbol, nextValue: unknown], + next: NextFunction + ): boolean + + getProperty?( + data: [propertyName: string | symbol, receiver: Target], + next: NextFunction + ): void +} + +export type NextFunction = () => ReturnType + +export function createProxy( + target: Target, + options: ProxyOptions +): Target { + const proxy = new Proxy(target, optionsToProxyHandler(options)) + + return proxy +} + +function optionsToProxyHandler>( + options: ProxyOptions +): ProxyHandler { + const { constructorCall, methodCall, getProperty, setProperty } = options + const handler: ProxyHandler = {} + + if (typeof constructorCall !== 'undefined') { + handler.construct = function (target, args, newTarget) { + const next = Reflect.construct.bind(null, target as any, args, newTarget) + return constructorCall.call(newTarget, args, next) + } + } + + handler.set = function (target, propertyName, nextValue) { + const next = () => { + const propertySource = findPropertySource(target, propertyName) || target + const ownDescriptors = Reflect.getOwnPropertyDescriptor( + propertySource, + propertyName + ) + + // Respect any custom setters present for this property. + if (typeof ownDescriptors?.set !== 'undefined') { + ownDescriptors.set.apply(target, [nextValue]) + return true + } + + // Otherwise, set the property on the source. + return Reflect.defineProperty(propertySource, propertyName, { + writable: true, + enumerable: true, + configurable: true, + value: nextValue, + }) + } + + if (typeof setProperty !== 'undefined') { + return setProperty.call(target, [propertyName, nextValue], next) + } + + return next() + } + + handler.get = function (target, propertyName, receiver) { + /** + * @note Using `Reflect.get()` here causes "TypeError: Illegal invocation". + */ + const next = () => target[propertyName as any] + + const value = + typeof getProperty !== 'undefined' + ? getProperty.call(target, [propertyName, receiver], next) + : next() + + if (typeof value === 'function') { + return (...args: Array) => { + const next = value.bind(target, ...args) + + if (typeof methodCall !== 'undefined') { + return methodCall.call(target, [propertyName as any, args], next) + } + + return next() + } + } + + return value + } + + return handler +} diff --git a/node_modules/@mswjs/interceptors/src/utils/emitAsync.ts b/node_modules/@mswjs/interceptors/src/utils/emitAsync.ts new file mode 100644 index 0000000000..09b43fcbee --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/emitAsync.ts @@ -0,0 +1,25 @@ +import { Emitter, EventMap } from 'strict-event-emitter' + +/** + * Emits an event on the given emitter but executes + * the listeners sequentially. This accounts for asynchronous + * listeners (e.g. those having "sleep" and handling the request). + */ +export async function emitAsync< + Events extends EventMap, + EventName extends keyof Events +>( + emitter: Emitter, + eventName: EventName, + ...data: Events[EventName] +): Promise { + const listners = emitter.listeners(eventName) + + if (listners.length === 0) { + return + } + + for (const listener of listners) { + await listener.apply(emitter, data) + } +} diff --git a/node_modules/@mswjs/interceptors/src/utils/fetchUtils.ts b/node_modules/@mswjs/interceptors/src/utils/fetchUtils.ts new file mode 100644 index 0000000000..37f7592941 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/fetchUtils.ts @@ -0,0 +1,93 @@ +export interface FetchResponseInit extends ResponseInit { + url?: string +} + +export class FetchResponse extends Response { + /** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ + static readonly STATUS_CODES_WITHOUT_BODY = [101, 103, 204, 205, 304] + + static readonly STATUS_CODES_WITH_REDIRECT = [301, 302, 303, 307, 308] + + static isConfigurableStatusCode(status: number): boolean { + return status >= 200 && status <= 599 + } + + static isRedirectResponse(status: number): boolean { + return FetchResponse.STATUS_CODES_WITH_REDIRECT.includes(status) + } + + /** + * Returns a boolean indicating whether the given response status + * code represents a response that can have a body. + */ + static isResponseWithBody(status: number): boolean { + return !FetchResponse.STATUS_CODES_WITHOUT_BODY.includes(status) + } + + static setUrl(url: string | undefined, response: Response): void { + if (!url) { + return + } + + if (response.url != '') { + return + } + + Object.defineProperty(response, 'url', { + value: url, + enumerable: true, + configurable: true, + writable: false, + }) + } + + /** + * Parses the given raw HTTP headers into a Fetch API `Headers` instance. + */ + static parseRawHeaders(rawHeaders: Array): Headers { + const headers = new Headers() + for (let line = 0; line < rawHeaders.length; line += 2) { + headers.append(rawHeaders[line], rawHeaders[line + 1]) + } + return headers + } + + constructor(body?: BodyInit | null, init: FetchResponseInit = {}) { + const status = init.status ?? 200 + const safeStatus = FetchResponse.isConfigurableStatusCode(status) + ? status + : 200 + const finalBody = FetchResponse.isResponseWithBody(status) ? body : null + + super(finalBody, { + ...init, + status: safeStatus, + }) + + if (status !== safeStatus) { + /** + * @note Undici keeps an internal "Symbol(state)" that holds + * the actual value of response status. Update that in Node.js. + */ + const stateSymbol = Object.getOwnPropertySymbols(this).find( + (symbol) => symbol.description === 'state' + ) + if (stateSymbol) { + const state = Reflect.get(this, stateSymbol) as object + Reflect.set(state, 'status', status) + } else { + Object.defineProperty(this, 'status', { + value: status, + enumerable: true, + configurable: true, + writable: false, + }) + } + } + + FetchResponse.setUrl(init.url, this) + } +} diff --git a/node_modules/@mswjs/interceptors/src/utils/findPropertySource.test.ts b/node_modules/@mswjs/interceptors/src/utils/findPropertySource.test.ts new file mode 100644 index 0000000000..cce02ca9eb --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/findPropertySource.test.ts @@ -0,0 +1,27 @@ +import { it, expect } from 'vitest' +import { findPropertySource } from './findPropertySource' + +it('returns the source for objects without prototypes', () => { + const obj = Object.create(null) + obj.test = undefined + const source = findPropertySource(obj, 'test') + expect(source).toBe(obj) +}) + +it('returns the source for objects with prototypes', () => { + const prototype = Object.create(null) + prototype.test = undefined + + const obj = Object.create(prototype) + + const source = findPropertySource(obj, 'test') + expect(source).toBe(prototype) +}) + +it('returns null if the prototype chain does not contain the property', () => { + const prototype = Object.create(null) + const obj = Object.create(prototype) + + const source = findPropertySource(obj, 'test') + expect(source).toBeNull() +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/findPropertySource.ts b/node_modules/@mswjs/interceptors/src/utils/findPropertySource.ts new file mode 100644 index 0000000000..26ca44af82 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/findPropertySource.ts @@ -0,0 +1,20 @@ +/** + * Returns the source object of the given property on the target object + * (the target itself, any parent in its prototype, or null). + */ +export function findPropertySource( + target: object, + propertyName: string | symbol +): object | null { + if (!(propertyName in target)) { + return null + } + + const hasProperty = Object.prototype.hasOwnProperty.call(target, propertyName) + if (hasProperty) { + return target + } + + const prototype = Reflect.getPrototypeOf(target) + return prototype ? findPropertySource(prototype, propertyName) : null +} diff --git a/node_modules/@mswjs/interceptors/src/utils/getCleanUrl.test.ts b/node_modules/@mswjs/interceptors/src/utils/getCleanUrl.test.ts new file mode 100644 index 0000000000..9f70ca81d5 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/getCleanUrl.test.ts @@ -0,0 +1,32 @@ +import { describe, it, expect } from 'vitest' +import { getCleanUrl } from './getCleanUrl' + +describe('getCleanUrl', () => { + describe('given a URL without query parameters', () => { + it('should return url href as-is', () => { + const url = new URL('https://github.com') + expect(getCleanUrl(url)).toEqual('https://github.com/') + }) + }) + + describe('given a URL with query parameters', () => { + it('should return url without parameters', () => { + const url = new URL('https://github.com/mswjs/?userId=abc-123') + expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/') + }) + }) + + describe('given a URL with a hash', () => { + it('should return a url without hash', () => { + const url = new URL('https://github.com/mswjs/#hello-world') + expect(getCleanUrl(url)).toEqual('https://github.com/mswjs/') + }) + }) + + describe('given an absolute URL ', () => { + it('should return a clean relative URL', () => { + const url = new URL('/login?query=value', 'https://github.com') + expect(getCleanUrl(url, false)).toEqual('/login') + }) + }) +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/getCleanUrl.ts b/node_modules/@mswjs/interceptors/src/utils/getCleanUrl.ts new file mode 100644 index 0000000000..14165674a3 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/getCleanUrl.ts @@ -0,0 +1,6 @@ +/** + * Removes query parameters and hashes from a given URL. + */ +export function getCleanUrl(url: URL, isAbsolute: boolean = true): string { + return [isAbsolute && url.origin, url.pathname].filter(Boolean).join('') +} diff --git a/node_modules/@mswjs/interceptors/src/utils/getUrlByRequestOptions.test.ts b/node_modules/@mswjs/interceptors/src/utils/getUrlByRequestOptions.test.ts new file mode 100644 index 0000000000..cc9423609d --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/getUrlByRequestOptions.test.ts @@ -0,0 +1,163 @@ +import { it, expect } from 'vitest' +import { Agent as HttpAgent } from 'http' +import { RequestOptions, Agent as HttpsAgent } from 'https' +import { getUrlByRequestOptions } from './getUrlByRequestOptions' + +it('returns a URL based on the basic RequestOptions', () => { + expect( + getUrlByRequestOptions({ + protocol: 'https:', + host: '127.0.0.1', + path: '/resource', + }).href + ).toBe('https://127.0.0.1/resource') +}) + +it('inherits protocol and port from http.Agent, if set', () => { + expect( + getUrlByRequestOptions({ + host: '127.0.0.1', + path: '/', + agent: new HttpAgent(), + }).href + ).toBe('http://127.0.0.1/') +}) + +it('inherits protocol and port from https.Agent, if set', () => { + expect( + getUrlByRequestOptions({ + host: '127.0.0.1', + path: '/', + agent: new HttpsAgent({ + port: 3080, + }), + }).href + ).toBe('https://127.0.0.1:3080/') +}) + +it('resolves protocol to "http" given no explicit protocol and no certificate', () => { + expect( + getUrlByRequestOptions({ + host: '127.0.0.1', + path: '/', + }).href + ).toBe('http://127.0.0.1/') +}) + +it('resolves protocol to "https" given no explicit protocol, but certificate', () => { + expect( + getUrlByRequestOptions({ + host: '127.0.0.1', + path: '/secure', + cert: '', + }).href + ).toBe('https://127.0.0.1/secure') +}) + +it('resolves protocol to "https" given no explicit protocol, but port is 443', () => { + expect( + getUrlByRequestOptions({ + host: '127.0.0.1', + port: 443, + path: '/resource', + }).href + ).toBe('https://127.0.0.1/resource') +}) + +it('resolves protocol to "https" given no explicit protocol, but agent port is 443', () => { + expect( + getUrlByRequestOptions({ + host: '127.0.0.1', + agent: new HttpsAgent({ + port: 443, + }), + path: '/resource', + }).href + ).toBe('https://127.0.0.1/resource') +}) + +it('respects explicitly provided port', () => { + expect( + getUrlByRequestOptions({ + protocol: 'http:', + host: '127.0.0.1', + port: 4002, + path: '/', + }).href + ).toBe('http://127.0.0.1:4002/') +}) + +it('inherits "username" and "password"', () => { + const url = getUrlByRequestOptions({ + protocol: 'https:', + host: '127.0.0.1', + path: '/user', + auth: 'admin:abc-123', + }) + + expect(url).toBeInstanceOf(URL) + expect(url).toHaveProperty('username', 'admin') + expect(url).toHaveProperty('password', 'abc-123') + expect(url).toHaveProperty('href', 'https://admin:abc-123@127.0.0.1/user') +}) + +it('resolves hostname to localhost if none provided', () => { + expect(getUrlByRequestOptions({}).hostname).toBe('localhost') +}) + +it('resolves host to localhost if none provided', () => { + expect(getUrlByRequestOptions({}).host).toBe('localhost') +}) + +it('supports "hostname" and "port"', () => { + const options: RequestOptions = { + protocol: 'https:', + hostname: '127.0.0.1', + port: 1234, + path: '/resource', + } + + expect(getUrlByRequestOptions(options).href).toBe( + 'https://127.0.0.1:1234/resource' + ) +}) + +it('use "hostname" if both "hostname" and "host" are specified', () => { + const options: RequestOptions = { + protocol: 'https:', + host: 'host', + hostname: 'hostname', + path: '/resource', + } + + expect(getUrlByRequestOptions(options).href).toBe( + 'https://hostname/resource' + ) +}) + +it('parses "host" in IPv6', () => { + expect( + getUrlByRequestOptions({ + host: '::1', + path: '/resource', + }).href + ).toBe('http://[::1]/resource') + + expect( + getUrlByRequestOptions({ + host: '[::1]', + path: '/resource', + }).href + ).toBe('http://[::1]/resource') + +}) + +it('parses "host" and "port" in IPv6', () => { + expect( + getUrlByRequestOptions({ + host: '::1', + port: 3001, + path: '/resource', + }).href + ).toBe('http://[::1]:3001/resource') +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/getUrlByRequestOptions.ts b/node_modules/@mswjs/interceptors/src/utils/getUrlByRequestOptions.ts new file mode 100644 index 0000000000..0b8a5ef760 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/getUrlByRequestOptions.ts @@ -0,0 +1,152 @@ +import { Agent } from 'http' +import { RequestOptions, Agent as HttpsAgent } from 'https' +import { Logger } from '@open-draft/logger' + +const logger = new Logger('utils getUrlByRequestOptions') + +// Request instance constructed by the "request" library +// has a "self" property that has a "uri" field. This is +// reproducible by performing a "XMLHttpRequest" request in JSDOM. +export interface RequestSelf { + uri?: URL +} + +export type ResolvedRequestOptions = RequestOptions & RequestSelf + +export const DEFAULT_PATH = '/' +const DEFAULT_PROTOCOL = 'http:' +const DEFAULT_HOSTNAME = 'localhost' +const SSL_PORT = 443 + +function getAgent( + options: ResolvedRequestOptions +): Agent | HttpsAgent | undefined { + return options.agent instanceof Agent ? options.agent : undefined +} + +function getProtocolByRequestOptions(options: ResolvedRequestOptions): string { + if (options.protocol) { + return options.protocol + } + + const agent = getAgent(options) + const agentProtocol = (agent as RequestOptions)?.protocol + + if (agentProtocol) { + return agentProtocol + } + + const port = getPortByRequestOptions(options) + const isSecureRequest = options.cert || port === SSL_PORT + + return isSecureRequest ? 'https:' : options.uri?.protocol || DEFAULT_PROTOCOL +} + +function getPortByRequestOptions( + options: ResolvedRequestOptions +): number | undefined { + // Use the explicitly provided port. + if (options.port) { + return Number(options.port) + } + + // Otherwise, try to resolve port from the agent. + const agent = getAgent(options) + + if ((agent as HttpsAgent)?.options.port) { + return Number((agent as HttpsAgent).options.port) + } + + if ((agent as RequestOptions)?.defaultPort) { + return Number((agent as RequestOptions).defaultPort) + } + + // Lastly, return undefined indicating that the port + // must inferred from the protocol. Do not infer it here. + return undefined +} + +interface RequestAuth { + username: string + password: string +} + +function getAuthByRequestOptions( + options: ResolvedRequestOptions +): RequestAuth | undefined { + if (options.auth) { + const [username, password] = options.auth.split(':') + return { username, password } + } +} + +/** + * Returns true if host looks like an IPv6 address without surrounding brackets + * It assumes any host containing `:` is definitely not IPv4 and probably IPv6, + * but note that this could include invalid IPv6 addresses as well. + */ +function isRawIPv6Address(host: string): boolean { + return host.includes(':') && !host.startsWith('[') && !host.endsWith(']') +} + +function getHostname(options: ResolvedRequestOptions): string | undefined { + let host = options.hostname || options.host + + if (host) { + if (isRawIPv6Address(host)) { + host = `[${host}]` + } + + // Check the presence of the port, and if it's present, + // remove it from the host, returning a hostname. + return new URL(`http://${host}`).hostname + } + + return DEFAULT_HOSTNAME +} + +/** + * Creates a `URL` instance from a given `RequestOptions` object. + */ +export function getUrlByRequestOptions(options: ResolvedRequestOptions): URL { + logger.info('request options', options) + + if (options.uri) { + logger.info( + 'constructing url from explicitly provided "options.uri": %s', + options.uri + ) + return new URL(options.uri.href) + } + + logger.info('figuring out url from request options...') + + const protocol = getProtocolByRequestOptions(options) + logger.info('protocol', protocol) + + const port = getPortByRequestOptions(options) + logger.info('port', port) + + const hostname = getHostname(options) + logger.info('hostname', hostname) + + const path = options.path || DEFAULT_PATH + logger.info('path', path) + + const credentials = getAuthByRequestOptions(options) + logger.info('credentials', credentials) + + const authString = credentials + ? `${credentials.username}:${credentials.password}@` + : '' + logger.info('auth string:', authString) + + const portString = typeof port !== 'undefined' ? `:${port}` : '' + const url = new URL(`${protocol}//${hostname}${portString}${path}`) + url.username = credentials?.username || '' + url.password = credentials?.password || '' + + logger.info('created url:', url) + + return url +} diff --git a/node_modules/@mswjs/interceptors/src/utils/getValueBySymbol.test.ts b/node_modules/@mswjs/interceptors/src/utils/getValueBySymbol.test.ts new file mode 100644 index 0000000000..9e2b21c8ce --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/getValueBySymbol.test.ts @@ -0,0 +1,14 @@ +import { it, expect } from 'vitest' +import { getValueBySymbol } from './getValueBySymbol' + +it('returns undefined given a non-existing symbol', () => { + expect(getValueBySymbol('non-existing', {})).toBeUndefined() +}) + +it('returns value behind the given symbol', () => { + const symbol = Symbol('kInternal') + + expect(getValueBySymbol('kInternal', { [symbol]: null })).toBe(null) + expect(getValueBySymbol('kInternal', { [symbol]: true })).toBe(true) + expect(getValueBySymbol('kInternal', { [symbol]: 'value' })).toBe('value') +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/getValueBySymbol.ts b/node_modules/@mswjs/interceptors/src/utils/getValueBySymbol.ts new file mode 100644 index 0000000000..2c2e9541f4 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/getValueBySymbol.ts @@ -0,0 +1,19 @@ +/** + * Returns the value behind the symbol with the given name. + */ +export function getValueBySymbol( + symbolName: string, + source: object +): T | undefined { + const ownSymbols = Object.getOwnPropertySymbols(source) + + const symbol = ownSymbols.find((symbol) => { + return symbol.description === symbolName + }) + + if (symbol) { + return Reflect.get(source, symbol) + } + + return +} diff --git a/node_modules/@mswjs/interceptors/src/utils/handleRequest.ts b/node_modules/@mswjs/interceptors/src/utils/handleRequest.ts new file mode 100644 index 0000000000..546f62ab6c --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/handleRequest.ts @@ -0,0 +1,217 @@ +import type { Emitter } from 'strict-event-emitter' +import { DeferredPromise } from '@open-draft/deferred-promise' +import { until } from '@open-draft/until' +import type { HttpRequestEventMap } from '../glossary' +import { emitAsync } from './emitAsync' +import { kResponsePromise, RequestController } from '../RequestController' +import { + createServerErrorResponse, + isResponseError, + ResponseError, +} from './responseUtils' +import { InterceptorError } from '../InterceptorError' +import { isNodeLikeError } from './isNodeLikeError' + +interface HandleRequestOptions { + requestId: string + request: Request + emitter: Emitter + controller: RequestController + + /** + * Called when the request has been handled + * with the given `Response` instance. + */ + onResponse: (response: Response) => void | Promise + + /** + * Called when the request has been handled + * with the given `Response.error()` instance. + */ + onRequestError: (response: ResponseError) => void + + /** + * Called when an unhandled error happens during the + * request handling. This is never a thrown error/response. + */ + onError: (error: unknown) => void +} + +/** + * @returns {Promise} Indicates whether the request has been handled. + */ +export async function handleRequest( + options: HandleRequestOptions +): Promise { + const handleResponse = async (response: Response | Error) => { + if (response instanceof Error) { + options.onError(response) + } + + // Handle "Response.error()" instances. + else if (isResponseError(response)) { + options.onRequestError(response) + } else { + await options.onResponse(response) + } + + return true + } + + const handleResponseError = async (error: unknown): Promise => { + // Forward the special interceptor error instances + // to the developer. These must not be handled in any way. + if (error instanceof InterceptorError) { + throw result.error + } + + // Support mocking Node.js-like errors. + if (isNodeLikeError(error)) { + options.onError(error) + return true + } + + // Handle thrown responses. + if (error instanceof Response) { + return await handleResponse(error) + } + + return false + } + + // Add the last "request" listener to check if the request + // has been handled in any way. If it hasn't, resolve the + // response promise with undefined. + options.emitter.once('request', ({ requestId: pendingRequestId }) => { + if (pendingRequestId !== options.requestId) { + return + } + + if (options.controller[kResponsePromise].state === 'pending') { + options.controller[kResponsePromise].resolve(undefined) + } + }) + + const requestAbortPromise = new DeferredPromise() + + /** + * @note `signal` is not always defined in React Native. + */ + if (options.request.signal) { + if (options.request.signal.aborted) { + requestAbortPromise.reject(options.request.signal.reason) + } else { + options.request.signal.addEventListener( + 'abort', + () => { + requestAbortPromise.reject(options.request.signal.reason) + }, + { once: true } + ) + } + } + + const result = await until(async () => { + // Emit the "request" event and wait until all the listeners + // for that event are finished (e.g. async listeners awaited). + // By the end of this promise, the developer cannot affect the + // request anymore. + const requestListtenersPromise = emitAsync(options.emitter, 'request', { + requestId: options.requestId, + request: options.request, + controller: options.controller, + }) + + await Promise.race([ + // Short-circuit the request handling promise if the request gets aborted. + requestAbortPromise, + requestListtenersPromise, + options.controller[kResponsePromise], + ]) + + // The response promise will settle immediately once + // the developer calls either "respondWith" or "errorWith". + const mockedResponse = await options.controller[kResponsePromise] + return mockedResponse + }) + + // Handle the request being aborted while waiting for the request listeners. + if (requestAbortPromise.state === 'rejected') { + options.onError(requestAbortPromise.rejectionReason) + return true + } + + if (result.error) { + // Handle the error during the request listener execution. + // These can be thrown responses or request errors. + if (await handleResponseError(result.error)) { + return true + } + + // If the developer has added "unhandledException" listeners, + // allow them to handle the error. They can translate it to a + // mocked response, network error, or forward it as-is. + if (options.emitter.listenerCount('unhandledException') > 0) { + // Create a new request controller just for the unhandled exception case. + // This is needed because the original controller might have been already + // interacted with (e.g. "respondWith" or "errorWith" called on it). + const unhandledExceptionController = new RequestController( + options.request + ) + + await emitAsync(options.emitter, 'unhandledException', { + error: result.error, + request: options.request, + requestId: options.requestId, + controller: unhandledExceptionController, + }).then(() => { + // If all the "unhandledException" listeners have finished + // but have not handled the response in any way, preemptively + // resolve the pending response promise from the new controller. + // This prevents it from hanging forever. + if ( + unhandledExceptionController[kResponsePromise].state === 'pending' + ) { + unhandledExceptionController[kResponsePromise].resolve(undefined) + } + }) + + const nextResult = await until( + () => unhandledExceptionController[kResponsePromise] + ) + + /** + * @note Handle the result of the unhandled controller + * in the same way as the original request controller. + * The exception here is that thrown errors within the + * "unhandledException" event do NOT result in another + * emit of the same event. They are forwarded as-is. + */ + if (nextResult.error) { + return handleResponseError(nextResult.error) + } + + if (nextResult.data) { + return handleResponse(nextResult.data) + } + } + + // Otherwise, coerce unhandled exceptions to a 500 Internal Server Error response. + options.onResponse(createServerErrorResponse(result.error)) + return true + } + + /** + * Handle a mocked Response instance. + * @note That this can also be an Error in case + * the developer called "errorWith". This differentiates + * unhandled exceptions from intended errors. + */ + if (result.data) { + return handleResponse(result.data) + } + + // In all other cases, consider the request unhandled. + // The interceptor must perform it as-is. + return false +} diff --git a/node_modules/@mswjs/interceptors/src/utils/hasConfigurableGlobal.test.ts b/node_modules/@mswjs/interceptors/src/utils/hasConfigurableGlobal.test.ts new file mode 100644 index 0000000000..9bade24939 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/hasConfigurableGlobal.test.ts @@ -0,0 +1,83 @@ +import { vi, beforeAll, afterEach, afterAll, it, expect } from 'vitest' +import { hasConfigurableGlobal } from './hasConfigurableGlobal' + +beforeAll(() => { + vi.spyOn(console, 'error').mockImplementation(() => {}) +}) + +afterEach(() => { + vi.resetAllMocks() +}) + +afterAll(() => { + vi.restoreAllMocks() +}) + +it('returns true if the global property exists and is configurable', () => { + Object.defineProperty(global, '_existsAndConfigurable', { + value: 'something', + configurable: true, + }) + + expect(hasConfigurableGlobal('_existsAndConfigurable')).toBe(true) +}) + +it('returns false if the global property does not exist', () => { + expect(hasConfigurableGlobal('_non-existing')).toBe(false) +}) + +it('returns false for existing global with undefined as a value', () => { + Object.defineProperty(global, '_existsAndUndefined', { + value: undefined, + configurable: true, + }) + expect(hasConfigurableGlobal('_existsAndUndefined')).toBe(false) +}) + +it('returns false for existing global with null as a value', () => { + Object.defineProperty(global, '_existsAndNull', { + value: null, + configurable: true, + }) + expect(hasConfigurableGlobal('_existsAndNull')).toBe(false) +}) + +it('returns false for existing global with a getter that returns undefined', () => { + Object.defineProperty(global, '_existsGetterUndefined', { + get: () => undefined, + configurable: true, + }) + expect(hasConfigurableGlobal('_existsGetterUndefined')).toBe(false) +}) + +it('returns false and prints an error for implicitly non-configurable global property', () => { + Object.defineProperty(global, '_implicitlyNonConfigurable', { + value: 'something', + }) + + expect(hasConfigurableGlobal('_implicitlyNonConfigurable')).toBe(false) + expect(console.error).toHaveBeenCalledWith( + '[MSW] Failed to apply interceptor: the global `_implicitlyNonConfigurable` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.' + ) +}) + +it('returns false and prints an error for explicitly non-configurable global property', () => { + Object.defineProperty(global, '_explicitlyNonConfigurable', { + value: 'something', + configurable: false, + }) + + expect(hasConfigurableGlobal('_explicitlyNonConfigurable')).toBe(false) + expect(console.error).toHaveBeenCalledWith( + '[MSW] Failed to apply interceptor: the global `_explicitlyNonConfigurable` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.' + ) +}) + +it('returns false and prints an error for global property that only has a getter', () => { + Object.defineProperty(global, '_onlyGetter', { get: () => 'something' }) + + expect(hasConfigurableGlobal('_onlyGetter')).toBe(false) + expect(console.error).toHaveBeenCalledWith( + '[MSW] Failed to apply interceptor: the global `_onlyGetter` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.' + ) +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/hasConfigurableGlobal.ts b/node_modules/@mswjs/interceptors/src/utils/hasConfigurableGlobal.ts new file mode 100644 index 0000000000..c830453322 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/hasConfigurableGlobal.ts @@ -0,0 +1,34 @@ +/** + * Returns a boolean indicating whether the given global property + * is defined and is configurable. + */ +export function hasConfigurableGlobal(propertyName: string): boolean { + const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName) + + // The property is not set at all. + if (typeof descriptor === 'undefined') { + return false + } + + // The property is set to a getter that returns undefined. + if ( + typeof descriptor.get === 'function' && + typeof descriptor.get() === 'undefined' + ) { + return false + } + + // The property is set to a value equal to undefined. + if (typeof descriptor.get === 'undefined' && descriptor.value == null) { + return false + } + + if (typeof descriptor.set === 'undefined' && !descriptor.configurable) { + console.error( + `[MSW] Failed to apply interceptor: the global \`${propertyName}\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.` + ) + return false + } + + return true +} diff --git a/node_modules/@mswjs/interceptors/src/utils/isNodeLikeError.ts b/node_modules/@mswjs/interceptors/src/utils/isNodeLikeError.ts new file mode 100644 index 0000000000..f74dea789c --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/isNodeLikeError.ts @@ -0,0 +1,13 @@ +export function isNodeLikeError( + error: unknown +): error is NodeJS.ErrnoException { + if (error == null) { + return false + } + + if (!(error instanceof Error)) { + return false + } + + return 'code' in error && 'errno' in error +} diff --git a/node_modules/@mswjs/interceptors/src/utils/isObject.test.ts b/node_modules/@mswjs/interceptors/src/utils/isObject.test.ts new file mode 100644 index 0000000000..ea4e99d60a --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/isObject.test.ts @@ -0,0 +1,21 @@ +import { it, expect } from 'vitest' +import { isObject } from './isObject' + +it('returns true given an object', () => { + expect(isObject({})).toBe(true) + expect(isObject({ a: 1 })).toBe(true) +}) + +it('returns false given an object-like instance', () => { + expect(isObject([1])).toBe(false) + expect(isObject(function () {})).toBe(false) + expect(isObject(new Response())).toBe(false) +}) + +it('returns false given a non-object instance', () => { + expect(isObject(null)).toBe(false) + expect(isObject(undefined)).toBe(false) + expect(isObject(false)).toBe(false) + expect(isObject(123)).toBe(false) + expect(isObject(Symbol('object Object'))).toBe(false) +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/isObject.ts b/node_modules/@mswjs/interceptors/src/utils/isObject.ts new file mode 100644 index 0000000000..096e12ea52 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/isObject.ts @@ -0,0 +1,8 @@ +/** + * Determines if a given value is an instance of object. + */ +export function isObject(value: any, loose = false): value is T { + return loose + ? Object.prototype.toString.call(value).startsWith('[object ') + : Object.prototype.toString.call(value) === '[object Object]' +} diff --git a/node_modules/@mswjs/interceptors/src/utils/isPropertyAccessible.ts b/node_modules/@mswjs/interceptors/src/utils/isPropertyAccessible.ts new file mode 100644 index 0000000000..4a80a75bc4 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/isPropertyAccessible.ts @@ -0,0 +1,19 @@ +/** + * A function that validates if property access is possible on an object + * without throwing. It returns `true` if the property access is possible + * and `false` otherwise. + * + * Environments like miniflare will throw on property access on certain objects + * like Request and Response, for unimplemented properties. + */ +export function isPropertyAccessible>( + obj: Obj, + key: keyof Obj +) { + try { + obj[key] + return true + } catch { + return false + } +} diff --git a/node_modules/@mswjs/interceptors/src/utils/nextTick.ts b/node_modules/@mswjs/interceptors/src/utils/nextTick.ts new file mode 100644 index 0000000000..a080ca1e1f --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/nextTick.ts @@ -0,0 +1,11 @@ +export function nextTick(callback: () => void) { + setTimeout(callback, 0) +} + +export function nextTickAsync(callback: () => void) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(callback()) + }, 0) + }) +} diff --git a/node_modules/@mswjs/interceptors/src/utils/parseJson.test.ts b/node_modules/@mswjs/interceptors/src/utils/parseJson.test.ts new file mode 100644 index 0000000000..b021034816 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/parseJson.test.ts @@ -0,0 +1,10 @@ +import { it, expect } from 'vitest' +import { parseJson } from './parseJson' + +it('parses a given string into JSON', () => { + expect(parseJson('{"id":1}')).toEqual({ id: 1 }) +}) + +it('returns null given invalid JSON string', () => { + expect(parseJson('{"o:2\'')).toBeNull() +}) diff --git a/node_modules/@mswjs/interceptors/src/utils/parseJson.ts b/node_modules/@mswjs/interceptors/src/utils/parseJson.ts new file mode 100644 index 0000000000..af8d2e6da6 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/parseJson.ts @@ -0,0 +1,12 @@ +/** + * Parses a given string into JSON. + * Gracefully handles invalid JSON by returning `null`. + */ +export function parseJson(data: string): Record | null { + try { + const json = JSON.parse(data) + return json + } catch (_) { + return null + } +} diff --git a/node_modules/@mswjs/interceptors/src/utils/responseUtils.ts b/node_modules/@mswjs/interceptors/src/utils/responseUtils.ts new file mode 100644 index 0000000000..68cafbaf10 --- /dev/null +++ b/node_modules/@mswjs/interceptors/src/utils/responseUtils.ts @@ -0,0 +1,39 @@ +import { isPropertyAccessible } from './isPropertyAccessible' + +/** + * Creates a generic 500 Unhandled Exception response. + */ +export function createServerErrorResponse(body: unknown): Response { + return new Response( + JSON.stringify( + body instanceof Error + ? { + name: body.name, + message: body.message, + stack: body.stack, + } + : body + ), + { + status: 500, + statusText: 'Unhandled Exception', + headers: { + 'Content-Type': 'application/json', + }, + } + ) +} + +export type ResponseError = Response & { type: 'error' } + +/** + * Check if the given response is a `Response.error()`. + * + * @note Some environments, like Miniflare (Cloudflare) do not + * implement the "Response.type" property and throw on its access. + * Safely check if we can access "type" on "Response" before continuing. + * @see https://github.com/mswjs/msw/issues/1834 + */ +export function isResponseError(response: Response): response is ResponseError { + return isPropertyAccessible(response, 'type') && response.type === 'error' +} diff --git a/node_modules/@open-draft/deferred-promise/README.md b/node_modules/@open-draft/deferred-promise/README.md new file mode 100644 index 0000000000..e19d242ab6 --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/README.md @@ -0,0 +1,191 @@ +# Deferred Promise + +The `DeferredPromise` class is a Promise-compatible abstraction that defers resolving/rejecting promises to another closure. This class is primarily useful when one part of your system establishes as promise but another part of your system fulfills it. + +> This class is conceptually inspired by the [`createDeferredPromise()`](https://github.com/nodejs/node/blob/696fd4b14fc34cc2d01497a3abd9bb441b89be50/lib/internal/util.js#L468-L477) internal utility in Node.js. Unlike the Node.js implementation, however, `DeferredProimse` _extends_ a native `Promise`, allowing the consumer to handle deferred promises like regular promises (no `.promise` instance nesting). + +## Getting started + +```sh +npm install @open-draft/deferred-promise +``` + +## Documentation + +- [**`createDeferredExecutor()`**](#createdeferredexecutor) + - [`DeferredExecutor.state`](#deferredexecutorstate) + - [`DeferredExecutor.resolve()`](#deferredexecutorresolve) + - [`DeferredExecutor.reject()`](#deferredexecutorreject) + - [`DeferredExecutor.rejectionReason`](#deferredexecutorrejectionreason) +- [**Class: `DeferredPromise`**](#class-deferredpromise) + - [`new DeferredPromise()`](#new-defferedpromise) + - [`deferredPromise.state`](#deferredpromisestate) + - [`deferredPromise.resolve()`](#deferredpromiseresolve) + - [`deferredPromise.reject()`](#deferredpromisereject) + - [`deferredPromise.rejectionReason`](#deferredpromiserejectionreason) + +--- + +## `createDeferredExecutor()` + +Creates a Promise executor function that delegates its resolution to the current scope. + +```js +import { createDeferredExecutor } from '@open-draft/deferred-promise' + +const executor = createDeferredExecutor() +const promise = new Promise(executor) + +executor.resolve('hello') +// executor.reject(new Error('Reason')) +``` + +Deferred executor allows you to control any promise remotely and doesn't affect the Promise instance in any way. Similar to the [`DeferredPromise`](#class-deferredpromise) instance, the deferred executor exposes additional promise properties like `state`, `rejectionReason`, `resolve`, and `reject`. In fact, the `DeferredPromise` class is implemented on top of the deferred executor. + +```js +const executor = createDeferredExecutor() +const promise = new Promise(executor) + +executor.reject('reason') + +nextTick(() => { + console.log(executor.rejectionReason) // "reason" +}) +``` + +### `DeferredExecutor.state` + +- `<"pending" | "fulfilled" | "rejected">` **Default:** `"pending"` + +```js +const executor = createDeferredExecutor() +const promise = new Promise(executor) + +console.log(executor.state) // "pending" +``` + +Calling [`resolve()`](#deferredexecutorresolve) and [`reject()`](#deferredexecutorreject) methods of the executor transitions the state to "fulfilled" and "rejected" respectively. + +### `DeferredExecutor.resolve()` + +Resolves the promise with a given value. + +```js +const executor = createDeferredExecutor() +const promise = new Promise(executor) + +console.log(executor.state) // "pending" + +executor.resolve() + +// The promise state is still "pending" +// because promises are settled in the next microtask. +console.log(executor.state) // "pending" + +nextTick(() => { + // In the next microtask, the promise's state is resolved. + console.log(executor.state) // "fulfilled" +}) +``` + +### `DeferredExecutor.reject()` + +Rejects the promise with a given reason. + +```js +const executor = createDeferredExecutor() +const promise = new Promise(executor) + +executor.reject(new Error('Failed to fetch')) + +nextTick(() => { + console.log(executor.state) // "rejected" + console.log(executor.rejectionReason) // Error("Failed to fetch") +}) +``` + +You can access the rejection reason of the promise at any time by the [`rejectionReason`](#deferredexecutorrejectionreason) property of the deferred executor. + +### `DeferredExecutor.rejectionReason` + +Returns the reason of the promise rejection. If no reason has been provided to the `reject()` call, `undefined` is returned instead. + +```js +const executor = createDeferredExecutor() +const promise = new Promise(executor) + +promise.reject(new Error('Internal Server Error')) + +nextTick(() => { + console.log(promise.rejectionReason) // Error("Internal Server Error") +}) +``` + +--- + +## Class: `DeferredPromise` + +### `new DefferedPromise()` + +Creates a new instance of a deferred promise. + +```js +import { DeferredPromise } from '@open-draft/deferred-promise' + +const promise = new DeferredPromise() +``` + +A deferred promise is a Promise-compatible class that constructs a regular Promise instance under the hood, controlling it via the [deferred executor](#createdeferredexecutor). + +A deferred promise is fully compatible with the regular Promise, both type- and runtime-wise, e.g. a deferred promise can be chained and awaited normally. + +```js +const promise = new DefferredPromise() + .then((value) => value.toUpperCase()) + .then((value) => value.substring(0, 2)) + .catch((error) => console.error(error)) + +await promise +``` + +Unlike the regular Promise, however, a deferred promise doesn't accept the `executor` function as the constructor argument. Instead, the resolution of the deferred promise is deferred to the current scope (thus the name). + +```js +function getPort() { + // Notice that you don't provide any executor function + // when constructing a deferred promise. + const portPromise = new DeferredPromise() + + port.on('open', (port) => { + // Resolve the deferred promise whenever necessary. + portPromise.resolve(port) + }) + + // Return the deferred promise immediately. + return portPromise +} +``` + +Use the [`resolve()`](#deferredpromiseresolve) and [`reject()`](#deferredpromisereject) methods of the deferred promise instance to resolve and reject that promise respectively. + +### `deferredPromise.state` + +See [`DeferredExecutor.state`](#deferredexecutorstate) + +### `deferredPromise.resolve()` + +See [`DeferredExecutor.resolve()`](#deferredexecutorresolve) + +### `deferredPromise.reject()` + +See [`DeferredExecutor.reject()`](#deferredexecutorreject) + +### `deferredPromise.rejectionReason` + +See [`DeferredExecutor.rejectionReason`](#deferredexecutorrejectionreason) + +--- + +## Mentions + +- [Jonas Kuske](https://github.com/jonaskuske) for the phenomenal work around improving Promise-compliance. diff --git a/node_modules/@open-draft/deferred-promise/build/index.d.mts b/node_modules/@open-draft/deferred-promise/build/index.d.mts new file mode 100644 index 0000000000..f4206473c4 --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/build/index.d.mts @@ -0,0 +1,27 @@ +declare type PromiseState = 'pending' | 'fulfilled' | 'rejected'; +declare type Executor = ConstructorParameters>[0]; +declare type ResolveFunction = Parameters>[0]; +declare type RejectFunction = Parameters>[1]; +declare type DeferredPromiseExecutor = { + (resolve?: ResolveFunction, reject?: RejectFunction): void; + resolve: ResolveFunction; + reject: RejectFunction; + result?: Output; + state: PromiseState; + rejectionReason?: unknown; +}; +declare function createDeferredExecutor(): DeferredPromiseExecutor; + +declare class DeferredPromise extends Promise { + #private; + resolve: ResolveFunction; + reject: RejectFunction; + constructor(executor?: Executor | null); + get state(): PromiseState; + get rejectionReason(): unknown; + then(onFulfilled?: (value: Input) => ThenResult | PromiseLike, onRejected?: (reason: any) => CatchResult | PromiseLike): DeferredPromise; + catch(onRejected?: (reason: any) => CatchResult | PromiseLike): DeferredPromise; + finally(onfinally?: () => void | Promise): DeferredPromise; +} + +export { DeferredPromise, DeferredPromiseExecutor, Executor, PromiseState, RejectFunction, ResolveFunction, createDeferredExecutor }; diff --git a/node_modules/@open-draft/deferred-promise/build/index.d.ts b/node_modules/@open-draft/deferred-promise/build/index.d.ts new file mode 100644 index 0000000000..f4206473c4 --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/build/index.d.ts @@ -0,0 +1,27 @@ +declare type PromiseState = 'pending' | 'fulfilled' | 'rejected'; +declare type Executor = ConstructorParameters>[0]; +declare type ResolveFunction = Parameters>[0]; +declare type RejectFunction = Parameters>[1]; +declare type DeferredPromiseExecutor = { + (resolve?: ResolveFunction, reject?: RejectFunction): void; + resolve: ResolveFunction; + reject: RejectFunction; + result?: Output; + state: PromiseState; + rejectionReason?: unknown; +}; +declare function createDeferredExecutor(): DeferredPromiseExecutor; + +declare class DeferredPromise extends Promise { + #private; + resolve: ResolveFunction; + reject: RejectFunction; + constructor(executor?: Executor | null); + get state(): PromiseState; + get rejectionReason(): unknown; + then(onFulfilled?: (value: Input) => ThenResult | PromiseLike, onRejected?: (reason: any) => CatchResult | PromiseLike): DeferredPromise; + catch(onRejected?: (reason: any) => CatchResult | PromiseLike): DeferredPromise; + finally(onfinally?: () => void | Promise): DeferredPromise; +} + +export { DeferredPromise, DeferredPromiseExecutor, Executor, PromiseState, RejectFunction, ResolveFunction, createDeferredExecutor }; diff --git a/node_modules/@open-draft/deferred-promise/build/index.js b/node_modules/@open-draft/deferred-promise/build/index.js new file mode 100644 index 0000000000..8612d834cc --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/build/index.js @@ -0,0 +1,99 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + DeferredPromise: () => DeferredPromise, + createDeferredExecutor: () => createDeferredExecutor +}); +module.exports = __toCommonJS(src_exports); + +// src/createDeferredExecutor.ts +function createDeferredExecutor() { + const executor = (resolve, reject) => { + executor.state = "pending"; + executor.resolve = (data) => { + if (executor.state !== "pending") { + return; + } + executor.result = data; + const onFulfilled = (value) => { + executor.state = "fulfilled"; + return value; + }; + return resolve( + data instanceof Promise ? data : Promise.resolve(data).then(onFulfilled) + ); + }; + executor.reject = (reason) => { + if (executor.state !== "pending") { + return; + } + queueMicrotask(() => { + executor.state = "rejected"; + }); + return reject(executor.rejectionReason = reason); + }; + }; + return executor; +} + +// src/DeferredPromise.ts +var DeferredPromise = class extends Promise { + #executor; + resolve; + reject; + constructor(executor = null) { + const deferredExecutor = createDeferredExecutor(); + super((originalResolve, originalReject) => { + deferredExecutor(originalResolve, originalReject); + executor?.(deferredExecutor.resolve, deferredExecutor.reject); + }); + this.#executor = deferredExecutor; + this.resolve = this.#executor.resolve; + this.reject = this.#executor.reject; + } + get state() { + return this.#executor.state; + } + get rejectionReason() { + return this.#executor.rejectionReason; + } + then(onFulfilled, onRejected) { + return this.#decorate(super.then(onFulfilled, onRejected)); + } + catch(onRejected) { + return this.#decorate(super.catch(onRejected)); + } + finally(onfinally) { + return this.#decorate(super.finally(onfinally)); + } + #decorate(promise) { + return Object.defineProperties(promise, { + resolve: { configurable: true, value: this.resolve }, + reject: { configurable: true, value: this.reject } + }); + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + DeferredPromise, + createDeferredExecutor +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@open-draft/deferred-promise/build/index.js.map b/node_modules/@open-draft/deferred-promise/build/index.js.map new file mode 100644 index 0000000000..55123c69bf --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/build/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/index.ts","../src/createDeferredExecutor.ts","../src/DeferredPromise.ts"],"sourcesContent":["export * from './createDeferredExecutor'\nexport * from './DeferredPromise'\n","export type PromiseState = 'pending' | 'fulfilled' | 'rejected'\n\nexport type Executor = ConstructorParameters>[0]\nexport type ResolveFunction = Parameters>[0]\nexport type RejectFunction = Parameters>[1]\n\nexport type DeferredPromiseExecutor = {\n (resolve?: ResolveFunction, reject?: RejectFunction): void\n\n resolve: ResolveFunction\n reject: RejectFunction\n result?: Output\n state: PromiseState\n rejectionReason?: unknown\n}\nexport function createDeferredExecutor<\n Input = never,\n Output = Input\n>(): DeferredPromiseExecutor {\n const executor = >((\n resolve,\n reject\n ) => {\n executor.state = 'pending'\n\n executor.resolve = (data) => {\n if (executor.state !== 'pending') {\n return\n }\n\n executor.result = data as Output\n\n const onFulfilled = (value: Value) => {\n executor.state = 'fulfilled'\n return value\n }\n\n return resolve(\n data instanceof Promise ? data : Promise.resolve(data).then(onFulfilled)\n )\n }\n\n executor.reject = (reason) => {\n if (executor.state !== 'pending') {\n return\n }\n\n queueMicrotask(() => {\n executor.state = 'rejected'\n })\n\n return reject((executor.rejectionReason = reason))\n }\n })\n\n return executor\n}\n","import {\n type Executor,\n type RejectFunction,\n type ResolveFunction,\n type DeferredPromiseExecutor,\n createDeferredExecutor,\n} from './createDeferredExecutor'\n\nexport class DeferredPromise extends Promise {\n #executor: DeferredPromiseExecutor\n\n public resolve: ResolveFunction\n public reject: RejectFunction\n\n constructor(executor: Executor | null = null) {\n const deferredExecutor = createDeferredExecutor()\n super((originalResolve, originalReject) => {\n deferredExecutor(originalResolve, originalReject)\n executor?.(deferredExecutor.resolve, deferredExecutor.reject)\n })\n\n this.#executor = deferredExecutor\n this.resolve = this.#executor.resolve\n this.reject = this.#executor.reject\n }\n\n public get state() {\n return this.#executor.state\n }\n\n public get rejectionReason() {\n return this.#executor.rejectionReason\n }\n\n public then(\n onFulfilled?: (value: Input) => ThenResult | PromiseLike,\n onRejected?: (reason: any) => CatchResult | PromiseLike\n ) {\n return this.#decorate(super.then(onFulfilled, onRejected))\n }\n\n public catch(\n onRejected?: (reason: any) => CatchResult | PromiseLike\n ) {\n return this.#decorate(super.catch(onRejected))\n }\n\n public finally(onfinally?: () => void | Promise) {\n return this.#decorate(super.finally(onfinally))\n }\n\n #decorate(\n promise: Promise\n ): DeferredPromise {\n return Object.defineProperties(promise, {\n resolve: { configurable: true, value: this.resolve },\n reject: { configurable: true, value: this.reject },\n }) as DeferredPromise\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACeO,SAAS,yBAG4B;AAC1C,QAAM,WAAoD,CACxD,SACA,WACG;AACH,aAAS,QAAQ;AAEjB,aAAS,UAAU,CAAC,SAAS;AAC3B,UAAI,SAAS,UAAU,WAAW;AAChC;AAAA,MACF;AAEA,eAAS,SAAS;AAElB,YAAM,cAAc,CAAQ,UAAiB;AAC3C,iBAAS,QAAQ;AACjB,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,gBAAgB,UAAU,OAAO,QAAQ,QAAQ,IAAI,EAAE,KAAK,WAAW;AAAA,MACzE;AAAA,IACF;AAEA,aAAS,SAAS,CAAC,WAAW;AAC5B,UAAI,SAAS,UAAU,WAAW;AAChC;AAAA,MACF;AAEA,qBAAe,MAAM;AACnB,iBAAS,QAAQ;AAAA,MACnB,CAAC;AAED,aAAO,OAAQ,SAAS,kBAAkB,MAAO;AAAA,IACnD;AAAA,EACF;AAEA,SAAO;AACT;;;AChDO,IAAM,kBAAN,cAAqD,QAAe;AAAA,EACzE;AAAA,EAEO;AAAA,EACA;AAAA,EAEP,YAAY,WAAmC,MAAM;AACnD,UAAM,mBAAmB,uBAAuB;AAChD,UAAM,CAAC,iBAAiB,mBAAmB;AACzC,uBAAiB,iBAAiB,cAAc;AAChD,iBAAW,iBAAiB,SAAS,iBAAiB,MAAM;AAAA,IAC9D,CAAC;AAED,SAAK,YAAY;AACjB,SAAK,UAAU,KAAK,UAAU;AAC9B,SAAK,SAAS,KAAK,UAAU;AAAA,EAC/B;AAAA,EAEA,IAAW,QAAQ;AACjB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,IAAW,kBAAkB;AAC3B,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEO,KACL,aACA,YACA;AACA,WAAO,KAAK,UAAU,MAAM,KAAK,aAAa,UAAU,CAAC;AAAA,EAC3D;AAAA,EAEO,MACL,YACA;AACA,WAAO,KAAK,UAAU,MAAM,MAAM,UAAU,CAAC;AAAA,EAC/C;AAAA,EAEO,QAAQ,WAAuC;AACpD,WAAO,KAAK,UAAU,MAAM,QAAQ,SAAS,CAAC;AAAA,EAChD;AAAA,EAEA,UACE,SACqC;AACrC,WAAO,OAAO,iBAAiB,SAAS;AAAA,MACtC,SAAS,EAAE,cAAc,MAAM,OAAO,KAAK,QAAQ;AAAA,MACnD,QAAQ,EAAE,cAAc,MAAM,OAAO,KAAK,OAAO;AAAA,IACnD,CAAC;AAAA,EACH;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/@open-draft/deferred-promise/build/index.mjs b/node_modules/@open-draft/deferred-promise/build/index.mjs new file mode 100644 index 0000000000..a1a05c6cd2 --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/build/index.mjs @@ -0,0 +1,72 @@ +// src/createDeferredExecutor.ts +function createDeferredExecutor() { + const executor = (resolve, reject) => { + executor.state = "pending"; + executor.resolve = (data) => { + if (executor.state !== "pending") { + return; + } + executor.result = data; + const onFulfilled = (value) => { + executor.state = "fulfilled"; + return value; + }; + return resolve( + data instanceof Promise ? data : Promise.resolve(data).then(onFulfilled) + ); + }; + executor.reject = (reason) => { + if (executor.state !== "pending") { + return; + } + queueMicrotask(() => { + executor.state = "rejected"; + }); + return reject(executor.rejectionReason = reason); + }; + }; + return executor; +} + +// src/DeferredPromise.ts +var DeferredPromise = class extends Promise { + #executor; + resolve; + reject; + constructor(executor = null) { + const deferredExecutor = createDeferredExecutor(); + super((originalResolve, originalReject) => { + deferredExecutor(originalResolve, originalReject); + executor?.(deferredExecutor.resolve, deferredExecutor.reject); + }); + this.#executor = deferredExecutor; + this.resolve = this.#executor.resolve; + this.reject = this.#executor.reject; + } + get state() { + return this.#executor.state; + } + get rejectionReason() { + return this.#executor.rejectionReason; + } + then(onFulfilled, onRejected) { + return this.#decorate(super.then(onFulfilled, onRejected)); + } + catch(onRejected) { + return this.#decorate(super.catch(onRejected)); + } + finally(onfinally) { + return this.#decorate(super.finally(onfinally)); + } + #decorate(promise) { + return Object.defineProperties(promise, { + resolve: { configurable: true, value: this.resolve }, + reject: { configurable: true, value: this.reject } + }); + } +}; +export { + DeferredPromise, + createDeferredExecutor +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@open-draft/deferred-promise/build/index.mjs.map b/node_modules/@open-draft/deferred-promise/build/index.mjs.map new file mode 100644 index 0000000000..b2340f4a1f --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/build/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/createDeferredExecutor.ts","../src/DeferredPromise.ts"],"sourcesContent":["export type PromiseState = 'pending' | 'fulfilled' | 'rejected'\n\nexport type Executor = ConstructorParameters>[0]\nexport type ResolveFunction = Parameters>[0]\nexport type RejectFunction = Parameters>[1]\n\nexport type DeferredPromiseExecutor = {\n (resolve?: ResolveFunction, reject?: RejectFunction): void\n\n resolve: ResolveFunction\n reject: RejectFunction\n result?: Output\n state: PromiseState\n rejectionReason?: unknown\n}\nexport function createDeferredExecutor<\n Input = never,\n Output = Input\n>(): DeferredPromiseExecutor {\n const executor = >((\n resolve,\n reject\n ) => {\n executor.state = 'pending'\n\n executor.resolve = (data) => {\n if (executor.state !== 'pending') {\n return\n }\n\n executor.result = data as Output\n\n const onFulfilled = (value: Value) => {\n executor.state = 'fulfilled'\n return value\n }\n\n return resolve(\n data instanceof Promise ? data : Promise.resolve(data).then(onFulfilled)\n )\n }\n\n executor.reject = (reason) => {\n if (executor.state !== 'pending') {\n return\n }\n\n queueMicrotask(() => {\n executor.state = 'rejected'\n })\n\n return reject((executor.rejectionReason = reason))\n }\n })\n\n return executor\n}\n","import {\n type Executor,\n type RejectFunction,\n type ResolveFunction,\n type DeferredPromiseExecutor,\n createDeferredExecutor,\n} from './createDeferredExecutor'\n\nexport class DeferredPromise extends Promise {\n #executor: DeferredPromiseExecutor\n\n public resolve: ResolveFunction\n public reject: RejectFunction\n\n constructor(executor: Executor | null = null) {\n const deferredExecutor = createDeferredExecutor()\n super((originalResolve, originalReject) => {\n deferredExecutor(originalResolve, originalReject)\n executor?.(deferredExecutor.resolve, deferredExecutor.reject)\n })\n\n this.#executor = deferredExecutor\n this.resolve = this.#executor.resolve\n this.reject = this.#executor.reject\n }\n\n public get state() {\n return this.#executor.state\n }\n\n public get rejectionReason() {\n return this.#executor.rejectionReason\n }\n\n public then(\n onFulfilled?: (value: Input) => ThenResult | PromiseLike,\n onRejected?: (reason: any) => CatchResult | PromiseLike\n ) {\n return this.#decorate(super.then(onFulfilled, onRejected))\n }\n\n public catch(\n onRejected?: (reason: any) => CatchResult | PromiseLike\n ) {\n return this.#decorate(super.catch(onRejected))\n }\n\n public finally(onfinally?: () => void | Promise) {\n return this.#decorate(super.finally(onfinally))\n }\n\n #decorate(\n promise: Promise\n ): DeferredPromise {\n return Object.defineProperties(promise, {\n resolve: { configurable: true, value: this.resolve },\n reject: { configurable: true, value: this.reject },\n }) as DeferredPromise\n }\n}\n"],"mappings":";AAeO,SAAS,yBAG4B;AAC1C,QAAM,WAAoD,CACxD,SACA,WACG;AACH,aAAS,QAAQ;AAEjB,aAAS,UAAU,CAAC,SAAS;AAC3B,UAAI,SAAS,UAAU,WAAW;AAChC;AAAA,MACF;AAEA,eAAS,SAAS;AAElB,YAAM,cAAc,CAAQ,UAAiB;AAC3C,iBAAS,QAAQ;AACjB,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,gBAAgB,UAAU,OAAO,QAAQ,QAAQ,IAAI,EAAE,KAAK,WAAW;AAAA,MACzE;AAAA,IACF;AAEA,aAAS,SAAS,CAAC,WAAW;AAC5B,UAAI,SAAS,UAAU,WAAW;AAChC;AAAA,MACF;AAEA,qBAAe,MAAM;AACnB,iBAAS,QAAQ;AAAA,MACnB,CAAC;AAED,aAAO,OAAQ,SAAS,kBAAkB,MAAO;AAAA,IACnD;AAAA,EACF;AAEA,SAAO;AACT;;;AChDO,IAAM,kBAAN,cAAqD,QAAe;AAAA,EACzE;AAAA,EAEO;AAAA,EACA;AAAA,EAEP,YAAY,WAAmC,MAAM;AACnD,UAAM,mBAAmB,uBAAuB;AAChD,UAAM,CAAC,iBAAiB,mBAAmB;AACzC,uBAAiB,iBAAiB,cAAc;AAChD,iBAAW,iBAAiB,SAAS,iBAAiB,MAAM;AAAA,IAC9D,CAAC;AAED,SAAK,YAAY;AACjB,SAAK,UAAU,KAAK,UAAU;AAC9B,SAAK,SAAS,KAAK,UAAU;AAAA,EAC/B;AAAA,EAEA,IAAW,QAAQ;AACjB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,IAAW,kBAAkB;AAC3B,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEO,KACL,aACA,YACA;AACA,WAAO,KAAK,UAAU,MAAM,KAAK,aAAa,UAAU,CAAC;AAAA,EAC3D;AAAA,EAEO,MACL,YACA;AACA,WAAO,KAAK,UAAU,MAAM,MAAM,UAAU,CAAC;AAAA,EAC/C;AAAA,EAEO,QAAQ,WAAuC;AACpD,WAAO,KAAK,UAAU,MAAM,QAAQ,SAAS,CAAC;AAAA,EAChD;AAAA,EAEA,UACE,SACqC;AACrC,WAAO,OAAO,iBAAiB,SAAS;AAAA,MACtC,SAAS,EAAE,cAAc,MAAM,OAAO,KAAK,QAAQ;AAAA,MACnD,QAAQ,EAAE,cAAc,MAAM,OAAO,KAAK,OAAO;AAAA,IACnD,CAAC;AAAA,EACH;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/@open-draft/deferred-promise/package.json b/node_modules/@open-draft/deferred-promise/package.json new file mode 100644 index 0000000000..201c1c56cc --- /dev/null +++ b/node_modules/@open-draft/deferred-promise/package.json @@ -0,0 +1,49 @@ +{ + "name": "@open-draft/deferred-promise", + "version": "2.2.0", + "description": "A Promise-compatible abstraction that defers resolving/rejecting promises to another closure.", + "main": "./build/index.js", + "types": "./build/index.d.ts", + "module": "./build/index.mjs", + "exports": { + ".": { + "types": "./build/index.d.ts", + "require": "./build/index.js", + "default": "./build/index.mjs" + } + }, + "scripts": { + "test": "jest", + "test:compliance": "export NODE_OPTIONS=--loader=tsx || set NODE_OPTIONS=--loader=tsx&& npx -y promises-aplus-tests ./test/aplus-tests-adapter.ts", + "prebuild": "rimraf ./build", + "build": "tsup", + "release": "release publish" + }, + "files": [ + "./build" + ], + "keywords": [ + "promise", + "defer", + "deferred", + "resolve", + "reject", + "executor" + ], + "author": "Artem Zakharchenko", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/open-draft/deferred-promise" + }, + "devDependencies": { + "@ossjs/release": "^0.7.2", + "@types/jest": "^29.0.1", + "jest": "^29.0.3", + "rimraf": "^3.0.2", + "ts-jest": "^29.0.0", + "tsup": "^7.2.0", + "tsx": "^3.12.1", + "typescript": "^4.8.3" + } +} \ No newline at end of file diff --git a/node_modules/@open-draft/logger/LICENSE b/node_modules/@open-draft/logger/LICENSE new file mode 100644 index 0000000000..7868ade175 --- /dev/null +++ b/node_modules/@open-draft/logger/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2023—present Artem Zakharchenko + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@open-draft/logger/README.md b/node_modules/@open-draft/logger/README.md new file mode 100644 index 0000000000..2da7455957 --- /dev/null +++ b/node_modules/@open-draft/logger/README.md @@ -0,0 +1,225 @@ +# Logger + +Environment-agnostic, ESM-friendly logger for simple needs. + +## Why does this exist? + +I've been using `debug` for quite some time but wanted to migrate my projects to better ESM support. Alas, `debug` doesn't ship as ESM so I went and wrote this little logger just for my needs. You will likely see it printing useful data in Mock Service Worker and beyond. + +## Installation + +```sh +npm install @open-draft/logger +``` + +## Usage + +This package has the same API for both browser and Node.js and can run in those environments out of the box. + +```js +// app.js +import { Logger } from '@open-draft/logger' + +const logger = new Logger('parser') + +logger.info('starting parsing...') +logger.warning('found legacy document format') +logger.success('parsed 120 documents!') +``` + +Logging is disabled by default. To enable logging, provide the `DEBUG` environment variable: + +```sh +DEBUG=1 node ./app.js +``` + +> You can also use `true` instead of `1`. You can also use a specific logger's name to enable [logger filtering](#logger-filtering). + +## API + +- Class: `Logger` + - [`new Logger(name)`](#new-loggername) + - [`logger.debug(message, ...positionals)`](#loggerdebugmessage-positionals) + - [`logger.info(message, ...positionals)`](#loggerinfomessage-positionals) + - [`logger.success(message, ...positionals)`](#loggersuccessmessage-positionals) + - [`logger.warning(message, ...positionals)`](#loggerwarningmessage-positionals) + - [`logger.error(message, ...positionals)`](#loggererrormessage-positionals) + - [`logger.extend(name)`](#loggerextendprefix) + - [`logger.only(callback)`](#loggeronlycallback) + +### `new Logger(name)` + +- `name` `string` the name of the logger. + +Creates a new instance of the logger. Each message printed by the logger will be prefixed with the given `name`. You can have multiple loggers with different names for different areas of your system. + +```js +const logger = new Logger('parser') +``` + +> You can nest loggers via [`logger.extend()`](#loggerextendprefix). + +### `logger.debug(message, ...positionals)` + +- `message` `string` +- `positionals` `unknown[]` + +Prints a debug message. + +```js +logger.debug('no duplicates found, skipping...') +``` + +``` +12:34:56:789 [parser] no duplicates found, skipping... +``` + +### `logger.info(message, ...positionals)` + +- `message` `string` +- `positionals` `unknown[]` + +Prints an info message. + +```js +logger.info('new parse request') +``` + +``` +12:34:56:789 [parser] new parse request +``` + +### `logger.success(message, ...positionals)` + +- `message` `string` +- `positionals` `unknown[]` + +Prints a success message. + +```js +logger.success('prased 123 documents!') +``` + +``` +12:34:56:789 ✔ [parser] prased 123 documents! +``` + +### `logger.warning(message, ...positionals)` + +- `message` `string` +- `positionals` `unknown[]` + +Prints a warning. In Node.js, prints it to `process.stderr`. + +```js +logger.warning('found legacy document format') +``` + +``` +12:34:56:789 ⚠ [parser] found legacy document format +``` + +### `logger.error(message, ...positionals)` + +- `message` `string` +- `positionals` `unknown[]` + +Prints an error. In Node.js, prints it to `process.stderr`. + +```js +logger.error('failed to parse document') +``` + +``` +12:34:56:789 ✖ [parser] failed to parse document +``` + +### `logger.extend(prefix)` + +- `prefix` `string` Additional prefix to append to the logger's name. + +Creates a new logger out of the current one. + +```js +const logger = new Logger('parser') + +function parseRequest(request) { + const requestLogger = logger.extend(`${request.method} ${request.url}`) + requestLogger.info('start parsing...') +} +``` + +``` +12:34:56:789 [parser] [GET https://example.com] start parsing... +``` + +### `logger.only(callback)` + +Executes a given callback only when the logging is activated. Useful for computing additional information for logs. + +```js +logger.only(() => { + const documentSize = getSizeBytes(document) + logger.debug(`document size: ${documentSize}`) +}) +``` + +> You can nest `logger.*` methods in the callback to `logger.only()`. + +## Log levels + +You can specify the log levels to print using the `LOG_LEVEL` environment variable. + +There are the following log levels: + +- `debug` +- `info` +- `success` +- `warning` +- `error` + +> Providing no log level will print all the messages. + +Here's an example of how to print only warnings: + +```js +// app.js +import { Logger } from '@open-draft/logger' + +const logger = new Logger('parser') + +logger.info('some info') +logger.warning('some warning') +logger.error('some error') +``` + +```js +LOG_LEVEL=warning node ./app.js +``` + +``` +12:34:56:789 ⚠ [parser] some warning +``` + +## Logger filtering + +You can only print a specific logger by providing its name as the `DEBUG` environment variable. + +```js +// app.js +import { Logger } from '@open-draft/logger' + +const appLogger = new Logger('app') +const parserLogger = new Logger('parser') + +appLogger.info('starting app...') +parserLogger.info('creating a new parser...') +``` + +```sh +DEBUG=app node ./app.js +``` + +``` +12:34:56:789 [app] starting app... +``` diff --git a/node_modules/@open-draft/logger/lib/index.d.ts b/node_modules/@open-draft/logger/lib/index.d.ts new file mode 100644 index 0000000000..547acfcd0c --- /dev/null +++ b/node_modules/@open-draft/logger/lib/index.d.ts @@ -0,0 +1,83 @@ +type ColorFunction = (text: string) => void; +declare function yellow(text: string): string; +declare function blue(text: string): string; +declare function gray(text: string): string; +declare function red(text: string): string; +declare function green(text: string): string; + +type colors_ColorFunction = ColorFunction; +declare const colors_blue: typeof blue; +declare const colors_gray: typeof gray; +declare const colors_green: typeof green; +declare const colors_red: typeof red; +declare const colors_yellow: typeof yellow; +declare namespace colors { + export { + colors_ColorFunction as ColorFunction, + colors_blue as blue, + colors_gray as gray, + colors_green as green, + colors_red as red, + colors_yellow as yellow, + }; +} + +type LogLevel = 'debug' | 'info' | 'success' | 'warning' | 'error'; +type LogColors = keyof typeof colors; +interface LogEntry { + timestamp: Date; + level: LogLevel; + message: any; +} +declare class Logger { + private readonly name; + private prefix; + constructor(name: string); + extend(domain: string): Logger; + /** + * Print a debug message. + * @example + * logger.debug('no duplicates found, creating a document...') + */ + debug(message: any, ...positionals: Array): void; + /** + * Print an info message. + * @example + * logger.info('start parsing...') + */ + info(message: any, ...positionals: Array): (message: any, ...positionals: Array) => void; + /** + * Print a success message. + * @example + * logger.success('successfully created document') + */ + success(message: any, ...positionals: Array): void; + /** + * Print a warning. + * @example + * logger.warning('found legacy document format') + */ + warning(message: any, ...positionals: Array): void; + /** + * Print an error message. + * @example + * logger.error('something went wrong') + */ + error(message: any, ...positionals: Array): void; + /** + * Execute the given callback only when the logging is enabled. + * This is skipped in its entirety and has no runtime cost otherwise. + * This executes regardless of the log level. + * @example + * logger.only(() => { + * logger.info('additional info') + * }) + */ + only(callback: () => void): void; + private createEntry; + private logEntry; + private formatTimestamp; + private getWriter; +} + +export { LogColors, LogEntry, LogLevel, Logger }; diff --git a/node_modules/@open-draft/logger/lib/index.js b/node_modules/@open-draft/logger/lib/index.js new file mode 100644 index 0000000000..ac101aec65 --- /dev/null +++ b/node_modules/@open-draft/logger/lib/index.js @@ -0,0 +1,295 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Logger: () => Logger +}); +module.exports = __toCommonJS(src_exports); +var import_is_node_process = require("is-node-process"); +var import_outvariant = require("outvariant"); + +// src/colors.ts +var colors_exports = {}; +__export(colors_exports, { + blue: () => blue, + gray: () => gray, + green: () => green, + red: () => red, + yellow: () => yellow +}); +function yellow(text) { + return `\x1B[33m${text}\x1B[0m`; +} +function blue(text) { + return `\x1B[34m${text}\x1B[0m`; +} +function gray(text) { + return `\x1B[90m${text}\x1B[0m`; +} +function red(text) { + return `\x1B[31m${text}\x1B[0m`; +} +function green(text) { + return `\x1B[32m${text}\x1B[0m`; +} + +// src/index.ts +var IS_NODE = (0, import_is_node_process.isNodeProcess)(); +var Logger = class { + constructor(name) { + this.name = name; + this.prefix = `[${this.name}]`; + const LOGGER_NAME = getVariable("DEBUG"); + const LOGGER_LEVEL = getVariable("LOG_LEVEL"); + const isLoggingEnabled = LOGGER_NAME === "1" || LOGGER_NAME === "true" || typeof LOGGER_NAME !== "undefined" && this.name.startsWith(LOGGER_NAME); + if (isLoggingEnabled) { + this.debug = isDefinedAndNotEquals(LOGGER_LEVEL, "debug") ? noop : this.debug; + this.info = isDefinedAndNotEquals(LOGGER_LEVEL, "info") ? noop : this.info; + this.success = isDefinedAndNotEquals(LOGGER_LEVEL, "success") ? noop : this.success; + this.warning = isDefinedAndNotEquals(LOGGER_LEVEL, "warning") ? noop : this.warning; + this.error = isDefinedAndNotEquals(LOGGER_LEVEL, "error") ? noop : this.error; + } else { + this.info = noop; + this.success = noop; + this.warning = noop; + this.error = noop; + this.only = noop; + } + } + prefix; + extend(domain) { + return new Logger(`${this.name}:${domain}`); + } + /** + * Print a debug message. + * @example + * logger.debug('no duplicates found, creating a document...') + */ + debug(message, ...positionals) { + this.logEntry({ + level: "debug", + message: gray(message), + positionals, + prefix: this.prefix, + colors: { + prefix: "gray" + } + }); + } + /** + * Print an info message. + * @example + * logger.info('start parsing...') + */ + info(message, ...positionals) { + this.logEntry({ + level: "info", + message, + positionals, + prefix: this.prefix, + colors: { + prefix: "blue" + } + }); + const performance2 = new PerformanceEntry(); + return (message2, ...positionals2) => { + performance2.measure(); + this.logEntry({ + level: "info", + message: `${message2} ${gray(`${performance2.deltaTime}ms`)}`, + positionals: positionals2, + prefix: this.prefix, + colors: { + prefix: "blue" + } + }); + }; + } + /** + * Print a success message. + * @example + * logger.success('successfully created document') + */ + success(message, ...positionals) { + this.logEntry({ + level: "info", + message, + positionals, + prefix: `\u2714 ${this.prefix}`, + colors: { + timestamp: "green", + prefix: "green" + } + }); + } + /** + * Print a warning. + * @example + * logger.warning('found legacy document format') + */ + warning(message, ...positionals) { + this.logEntry({ + level: "warning", + message, + positionals, + prefix: `\u26A0 ${this.prefix}`, + colors: { + timestamp: "yellow", + prefix: "yellow" + } + }); + } + /** + * Print an error message. + * @example + * logger.error('something went wrong') + */ + error(message, ...positionals) { + this.logEntry({ + level: "error", + message, + positionals, + prefix: `\u2716 ${this.prefix}`, + colors: { + timestamp: "red", + prefix: "red" + } + }); + } + /** + * Execute the given callback only when the logging is enabled. + * This is skipped in its entirety and has no runtime cost otherwise. + * This executes regardless of the log level. + * @example + * logger.only(() => { + * logger.info('additional info') + * }) + */ + only(callback) { + callback(); + } + createEntry(level, message) { + return { + timestamp: /* @__PURE__ */ new Date(), + level, + message + }; + } + logEntry(args) { + const { + level, + message, + prefix, + colors: customColors, + positionals = [] + } = args; + const entry = this.createEntry(level, message); + const timestampColor = customColors?.timestamp || "gray"; + const prefixColor = customColors?.prefix || "gray"; + const colorize = { + timestamp: colors_exports[timestampColor], + prefix: colors_exports[prefixColor] + }; + const write = this.getWriter(level); + write( + [colorize.timestamp(this.formatTimestamp(entry.timestamp))].concat(prefix != null ? colorize.prefix(prefix) : []).concat(serializeInput(message)).join(" "), + ...positionals.map(serializeInput) + ); + } + formatTimestamp(timestamp) { + return `${timestamp.toLocaleTimeString( + "en-GB" + )}:${timestamp.getMilliseconds()}`; + } + getWriter(level) { + switch (level) { + case "debug": + case "success": + case "info": { + return log; + } + case "warning": { + return warn; + } + case "error": { + return error; + } + } + } +}; +var PerformanceEntry = class { + startTime; + endTime; + deltaTime; + constructor() { + this.startTime = performance.now(); + } + measure() { + this.endTime = performance.now(); + const deltaTime = this.endTime - this.startTime; + this.deltaTime = deltaTime.toFixed(2); + } +}; +var noop = () => void 0; +function log(message, ...positionals) { + if (IS_NODE) { + process.stdout.write((0, import_outvariant.format)(message, ...positionals) + "\n"); + return; + } + console.log(message, ...positionals); +} +function warn(message, ...positionals) { + if (IS_NODE) { + process.stderr.write((0, import_outvariant.format)(message, ...positionals) + "\n"); + return; + } + console.warn(message, ...positionals); +} +function error(message, ...positionals) { + if (IS_NODE) { + process.stderr.write((0, import_outvariant.format)(message, ...positionals) + "\n"); + return; + } + console.error(message, ...positionals); +} +function getVariable(variableName) { + if (IS_NODE) { + return process.env[variableName]; + } + return globalThis[variableName]?.toString(); +} +function isDefinedAndNotEquals(value, expected) { + return value !== void 0 && value !== expected; +} +function serializeInput(message) { + if (typeof message === "undefined") { + return "undefined"; + } + if (message === null) { + return "null"; + } + if (typeof message === "string") { + return message; + } + if (typeof message === "object") { + return JSON.stringify(message); + } + return message.toString(); +} diff --git a/node_modules/@open-draft/logger/lib/index.mjs b/node_modules/@open-draft/logger/lib/index.mjs new file mode 100644 index 0000000000..ffb0b88b7a --- /dev/null +++ b/node_modules/@open-draft/logger/lib/index.mjs @@ -0,0 +1,281 @@ +var __defProp = Object.defineProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; + +// src/index.ts +import { isNodeProcess } from "is-node-process"; +import { format } from "outvariant"; + +// src/colors.ts +var colors_exports = {}; +__export(colors_exports, { + blue: () => blue, + gray: () => gray, + green: () => green, + red: () => red, + yellow: () => yellow +}); +function yellow(text) { + return `\x1B[33m${text}\x1B[0m`; +} +function blue(text) { + return `\x1B[34m${text}\x1B[0m`; +} +function gray(text) { + return `\x1B[90m${text}\x1B[0m`; +} +function red(text) { + return `\x1B[31m${text}\x1B[0m`; +} +function green(text) { + return `\x1B[32m${text}\x1B[0m`; +} + +// src/index.ts +var IS_NODE = isNodeProcess(); +var Logger = class { + constructor(name) { + this.name = name; + this.prefix = `[${this.name}]`; + const LOGGER_NAME = getVariable("DEBUG"); + const LOGGER_LEVEL = getVariable("LOG_LEVEL"); + const isLoggingEnabled = LOGGER_NAME === "1" || LOGGER_NAME === "true" || typeof LOGGER_NAME !== "undefined" && this.name.startsWith(LOGGER_NAME); + if (isLoggingEnabled) { + this.debug = isDefinedAndNotEquals(LOGGER_LEVEL, "debug") ? noop : this.debug; + this.info = isDefinedAndNotEquals(LOGGER_LEVEL, "info") ? noop : this.info; + this.success = isDefinedAndNotEquals(LOGGER_LEVEL, "success") ? noop : this.success; + this.warning = isDefinedAndNotEquals(LOGGER_LEVEL, "warning") ? noop : this.warning; + this.error = isDefinedAndNotEquals(LOGGER_LEVEL, "error") ? noop : this.error; + } else { + this.info = noop; + this.success = noop; + this.warning = noop; + this.error = noop; + this.only = noop; + } + } + prefix; + extend(domain) { + return new Logger(`${this.name}:${domain}`); + } + /** + * Print a debug message. + * @example + * logger.debug('no duplicates found, creating a document...') + */ + debug(message, ...positionals) { + this.logEntry({ + level: "debug", + message: gray(message), + positionals, + prefix: this.prefix, + colors: { + prefix: "gray" + } + }); + } + /** + * Print an info message. + * @example + * logger.info('start parsing...') + */ + info(message, ...positionals) { + this.logEntry({ + level: "info", + message, + positionals, + prefix: this.prefix, + colors: { + prefix: "blue" + } + }); + const performance2 = new PerformanceEntry(); + return (message2, ...positionals2) => { + performance2.measure(); + this.logEntry({ + level: "info", + message: `${message2} ${gray(`${performance2.deltaTime}ms`)}`, + positionals: positionals2, + prefix: this.prefix, + colors: { + prefix: "blue" + } + }); + }; + } + /** + * Print a success message. + * @example + * logger.success('successfully created document') + */ + success(message, ...positionals) { + this.logEntry({ + level: "info", + message, + positionals, + prefix: `\u2714 ${this.prefix}`, + colors: { + timestamp: "green", + prefix: "green" + } + }); + } + /** + * Print a warning. + * @example + * logger.warning('found legacy document format') + */ + warning(message, ...positionals) { + this.logEntry({ + level: "warning", + message, + positionals, + prefix: `\u26A0 ${this.prefix}`, + colors: { + timestamp: "yellow", + prefix: "yellow" + } + }); + } + /** + * Print an error message. + * @example + * logger.error('something went wrong') + */ + error(message, ...positionals) { + this.logEntry({ + level: "error", + message, + positionals, + prefix: `\u2716 ${this.prefix}`, + colors: { + timestamp: "red", + prefix: "red" + } + }); + } + /** + * Execute the given callback only when the logging is enabled. + * This is skipped in its entirety and has no runtime cost otherwise. + * This executes regardless of the log level. + * @example + * logger.only(() => { + * logger.info('additional info') + * }) + */ + only(callback) { + callback(); + } + createEntry(level, message) { + return { + timestamp: /* @__PURE__ */ new Date(), + level, + message + }; + } + logEntry(args) { + const { + level, + message, + prefix, + colors: customColors, + positionals = [] + } = args; + const entry = this.createEntry(level, message); + const timestampColor = customColors?.timestamp || "gray"; + const prefixColor = customColors?.prefix || "gray"; + const colorize = { + timestamp: colors_exports[timestampColor], + prefix: colors_exports[prefixColor] + }; + const write = this.getWriter(level); + write( + [colorize.timestamp(this.formatTimestamp(entry.timestamp))].concat(prefix != null ? colorize.prefix(prefix) : []).concat(serializeInput(message)).join(" "), + ...positionals.map(serializeInput) + ); + } + formatTimestamp(timestamp) { + return `${timestamp.toLocaleTimeString( + "en-GB" + )}:${timestamp.getMilliseconds()}`; + } + getWriter(level) { + switch (level) { + case "debug": + case "success": + case "info": { + return log; + } + case "warning": { + return warn; + } + case "error": { + return error; + } + } + } +}; +var PerformanceEntry = class { + startTime; + endTime; + deltaTime; + constructor() { + this.startTime = performance.now(); + } + measure() { + this.endTime = performance.now(); + const deltaTime = this.endTime - this.startTime; + this.deltaTime = deltaTime.toFixed(2); + } +}; +var noop = () => void 0; +function log(message, ...positionals) { + if (IS_NODE) { + process.stdout.write(format(message, ...positionals) + "\n"); + return; + } + console.log(message, ...positionals); +} +function warn(message, ...positionals) { + if (IS_NODE) { + process.stderr.write(format(message, ...positionals) + "\n"); + return; + } + console.warn(message, ...positionals); +} +function error(message, ...positionals) { + if (IS_NODE) { + process.stderr.write(format(message, ...positionals) + "\n"); + return; + } + console.error(message, ...positionals); +} +function getVariable(variableName) { + if (IS_NODE) { + return process.env[variableName]; + } + return globalThis[variableName]?.toString(); +} +function isDefinedAndNotEquals(value, expected) { + return value !== void 0 && value !== expected; +} +function serializeInput(message) { + if (typeof message === "undefined") { + return "undefined"; + } + if (message === null) { + return "null"; + } + if (typeof message === "string") { + return message; + } + if (typeof message === "object") { + return JSON.stringify(message); + } + return message.toString(); +} +export { + Logger +}; diff --git a/node_modules/@open-draft/logger/package.json b/node_modules/@open-draft/logger/package.json new file mode 100644 index 0000000000..796aafc8d7 --- /dev/null +++ b/node_modules/@open-draft/logger/package.json @@ -0,0 +1,56 @@ +{ + "name": "@open-draft/logger", + "version": "0.3.0", + "description": "Environment-agnostic, ESM-friendly logger for simple needs.", + "main": "./lib/index.js", + "module": "./lib/index.mjs", + "types": "./lib/index.d.ts", + "exports": { + ".": { + "types": "./lib/index.d.ts", + "require": "./lib/index.js", + "import": "./lib/index.mjs", + "default": "./lib/index.js" + }, + "./package.json": "./package.json" + }, + "keywords": [ + "log", + "logger", + "logging", + "universal", + "tiny" + ], + "files": [ + "lib", + "LICENSE", + "README.md" + ], + "author": "Artem Zakharchenko", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/open-draft/logger" + }, + "devDependencies": { + "@ossjs/release": "^0.5.1", + "@playwright/test": "^1.32.3", + "@types/node": "^18.15.11", + "playwright": "^1.32.3", + "tsup": "^6.7.0", + "typescript": "^5.0.3", + "vitest": "^0.29.8", + "webpack-http-server": "^0.5.0" + }, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + }, + "scripts": { + "build": "tsup", + "test": "pnpm test:node && pnpm test:browser", + "test:node": "vitest run", + "test:browser": "playwright test", + "release": "release publish" + } +} \ No newline at end of file diff --git a/node_modules/@open-draft/until/LICENSE b/node_modules/@open-draft/until/LICENSE new file mode 100644 index 0000000000..8a1c628e51 --- /dev/null +++ b/node_modules/@open-draft/until/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Artem Zakharchenko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/@open-draft/until/README.md b/node_modules/@open-draft/until/README.md new file mode 100644 index 0000000000..be49a5049f --- /dev/null +++ b/node_modules/@open-draft/until/README.md @@ -0,0 +1,150 @@ +[![Latest release](https://img.shields.io/npm/v/@open-draft/until.svg)](https://www.npmjs.com/package/@open-draft/until) + +# `until` + +Gracefully handle a Promise using `async`/`await`. + +## Why? + +With the addition of `async`/`await` keywords in ECMAScript 2017 the handling of Promises became much easier. However, one must keep in mind that the `await` keyword provides no standard error handling API. Consider this usage: + +```js +function getUser(id) { + const data = await fetchUser(id) + // Work with "data"... +} +``` + +In case `fetchUser()` throws an error, the entire `getUser()` function's scope will terminate. Because of this, it's recommended to implement error handling using `try`/`catch` block wrapping `await` expressions: + +```js +function getUser(id) + let data = null + + try { + data = await asyncAction() + } catch (error) { + console.error(error) + } + + // Work with "data"... +} +``` + +While this is a semantically valid approach, constructing `try`/`catch` around each awaited operation may be tedious and get overlooked at times. Such error handling also introduces separate closures for execution and error scenarios of an asynchronous operation. + +This library encapsulates the `try`/`catch` error handling in a utility function that does not create a separate closure and exposes a NodeJS-friendly API to work with errors and resolved data. + +## Getting started + +### Install + +```bash +npm install @open-draft/until +``` + +### Usage + +```js +import { until } from '@open-draft/until' + +async function(id) { + const { error, data } = await until(() => fetchUser(id)) + + if (error) { + return handleError(error) + } + + return data +} +``` + +### Usage with TypeScript + +```ts +import { until } from '@open-draft/until' + +interface User { + firstName: string + age: number +} + +interface UserFetchError { + type: 'FORBIDDEN' | 'NOT_FOUND' + message?: string +} + +async function(id: string) { + const { error, data } = await until(() => fetchUser(id)) + + if (error) { + handleError(error.type, error.message) + } + + return data.firstName +} +``` + +## Frequently asked questions + +### Why does `until` accept a function and not a `Promise` directly? + +This has been intentionally introduced to await a single logical unit as opposed to a single `Promise`. + +```js +// Notice how a single "until" invocation can handle +// a rather complex piece of logic. This way any rejections +// or exceptions happening within the given function +// can be handled via the same "error". +const { error, data } = until(async () => { + const user = await fetchUser() + const nextUser = normalizeUser(user) + const transaction = await saveModel('user', user) + + invariant(transaction.status === 'OK', 'Saving user failed') + + return transaction.result +}) + +if (error) { + // Handle any exceptions happened within the function. +} +``` + +### Why does `until` return an object and not an array? + +The `until` function used to return an array of shape `[error, data]` prior to `2.0.0`. That has been changed, however, to get proper type-safety using discriminated union type. + +Compare these two examples: + +```ts +const [error, data] = await until(() => action()) + +if (error) { + return null +} + +// Data still has ambiguous "DataType | null" type here +// even after you've checked and handled the "error" above. +console.log(data) +``` + +```ts +const result = await until(() => action()) + +// At this point, "data" is ambiguous "DataType | null" +// which is correct, as you haven't checked nor handled the "error". + +if (result.error) { + return null +} + +// Data is strict "DataType" since you've handled the "error" above. +console.log(result.data) +``` + +> It's crucial to keep the entire result of the `Promise` in a single variable and not destructure it. TypeScript will always keep the type of `error` and `data` as it was upon destructuring, ignoring any type guards you may perform later on. + +## Special thanks + +- [giuseppegurgone](https://twitter.com/giuseppegurgone) for the discussion about the original `until` API. diff --git a/node_modules/@open-draft/until/lib/index.d.ts b/node_modules/@open-draft/until/lib/index.d.ts new file mode 100644 index 0000000000..19544f40af --- /dev/null +++ b/node_modules/@open-draft/until/lib/index.d.ts @@ -0,0 +1,15 @@ +type AsyncTuple = { + error: ErrorType; + data: null; +} | { + error: null; + data: DataType; +}; +/** + * Gracefully handles a given Promise factory. + * @example + * const { error, data } = await until(() => asyncAction()) + */ +declare const until: (promise: () => Promise) => Promise>; + +export { until }; diff --git a/node_modules/@open-draft/until/lib/index.js b/node_modules/@open-draft/until/lib/index.js new file mode 100644 index 0000000000..3944d95acf --- /dev/null +++ b/node_modules/@open-draft/until/lib/index.js @@ -0,0 +1,41 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + until: () => until +}); +module.exports = __toCommonJS(src_exports); + +// src/until.ts +var until = async (promise) => { + try { + const data = await promise().catch((error) => { + throw error; + }); + return { error: null, data }; + } catch (error) { + return { error, data: null }; + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + until +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/@open-draft/until/lib/index.js.map b/node_modules/@open-draft/until/lib/index.js.map new file mode 100644 index 0000000000..71429109f0 --- /dev/null +++ b/node_modules/@open-draft/until/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/index.ts","../src/until.ts"],"sourcesContent":["export { until } from './until'","export type AsyncTuple<\n ErrorType extends any = Error,\n DataType extends any = unknown,\n> =\n | {\n error: ErrorType\n data: null\n }\n | { error: null; data: DataType }\n\n/**\n * Gracefully handles a given Promise factory.\n * @example\n * const { error, data } = await until(() => asyncAction())\n */\nexport const until = async <\n ErrorType extends any = Error,\n DataType extends any = unknown,\n>(\n promise: () => Promise,\n): Promise> => {\n try {\n const data = await promise().catch((error) => {\n throw error\n })\n return { error: null, data }\n } catch (error) {\n return { error, data: null }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACeO,IAAM,QAAQ,OAInB,YAC6C;AAC7C,MAAI;AACF,UAAM,OAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,UAAU;AAC5C,YAAM;AAAA,IACR,CAAC;AACD,WAAO,EAAE,OAAO,MAAM,KAAK;AAAA,EAC7B,SAAS,OAAP;AACA,WAAO,EAAE,OAAO,MAAM,KAAK;AAAA,EAC7B;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/@open-draft/until/lib/index.mjs b/node_modules/@open-draft/until/lib/index.mjs new file mode 100644 index 0000000000..12be84c8d1 --- /dev/null +++ b/node_modules/@open-draft/until/lib/index.mjs @@ -0,0 +1,15 @@ +// src/until.ts +var until = async (promise) => { + try { + const data = await promise().catch((error) => { + throw error; + }); + return { error: null, data }; + } catch (error) { + return { error, data: null }; + } +}; +export { + until +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/@open-draft/until/lib/index.mjs.map b/node_modules/@open-draft/until/lib/index.mjs.map new file mode 100644 index 0000000000..6c246974fc --- /dev/null +++ b/node_modules/@open-draft/until/lib/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/until.ts"],"sourcesContent":["export type AsyncTuple<\n ErrorType extends any = Error,\n DataType extends any = unknown,\n> =\n | {\n error: ErrorType\n data: null\n }\n | { error: null; data: DataType }\n\n/**\n * Gracefully handles a given Promise factory.\n * @example\n * const { error, data } = await until(() => asyncAction())\n */\nexport const until = async <\n ErrorType extends any = Error,\n DataType extends any = unknown,\n>(\n promise: () => Promise,\n): Promise> => {\n try {\n const data = await promise().catch((error) => {\n throw error\n })\n return { error: null, data }\n } catch (error) {\n return { error, data: null }\n }\n}\n"],"mappings":";AAeO,IAAM,QAAQ,OAInB,YAC6C;AAC7C,MAAI;AACF,UAAM,OAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,UAAU;AAC5C,YAAM;AAAA,IACR,CAAC;AACD,WAAO,EAAE,OAAO,MAAM,KAAK;AAAA,EAC7B,SAAS,OAAP;AACA,WAAO,EAAE,OAAO,MAAM,KAAK;AAAA,EAC7B;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/@open-draft/until/package.json b/node_modules/@open-draft/until/package.json new file mode 100644 index 0000000000..a640d6031c --- /dev/null +++ b/node_modules/@open-draft/until/package.json @@ -0,0 +1,37 @@ +{ + "name": "@open-draft/until", + "version": "2.1.0", + "description": "Gracefully handle a Promise using async/await.", + "main": "./lib/index.js", + "module": "./lib/index.mjs", + "types": "./lib/index.d.ts", + "exports": { + ".": { + "types": "./lib/index.d.ts", + "require": "./lib/index.js", + "import": "./lib/index.mjs", + "default": "./lib/index.mjs" + } + }, + "repository": "open-draft/until", + "author": "Artem Zakharchenko ", + "license": "MIT", + "files": [ + "README.md", + "lib" + ], + "devDependencies": { + "@ossjs/release": "^0.5.1", + "@types/jest": "^26.0.22", + "jest": "^26.6.3", + "ts-jest": "^26.5.4", + "tsup": "^6.2.3", + "typescript": "^4.2.4" + }, + "scripts": { + "start": "tsc -w", + "test": "jest", + "build": "tsup", + "release": "release publish" + } +} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js index 7fc9deadcf..8b275fd224 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js @@ -107,86 +107,112 @@ exports.default = (0, util_1.createRule)({ create(context, [{ ignoreIntersections, ignoreUnions }]) { const parserServices = (0, util_1.getParserServices)(context); const { sourceCode } = context; + function report(messageId, constituentNode, data) { + const getUnionOrIntersectionToken = (where, at) => sourceCode[`getTokens${where}`](constituentNode, { + filter: token => ['&', '|'].includes(token.value) && + constituentNode.parent.range[0] <= token.range[0] && + token.range[1] <= constituentNode.parent.range[1], + }).at(at); + const beforeUnionOrIntersectionToken = getUnionOrIntersectionToken('Before', -1); + let afterUnionOrIntersectionToken; + let bracketBeforeTokens; + let bracketAfterTokens; + if (beforeUnionOrIntersectionToken) { + bracketBeforeTokens = sourceCode.getTokensBetween(beforeUnionOrIntersectionToken, constituentNode); + bracketAfterTokens = sourceCode.getTokensAfter(constituentNode, { + count: bracketBeforeTokens.length, + }); + } + else { + afterUnionOrIntersectionToken = (0, util_1.nullThrows)(getUnionOrIntersectionToken('After', 0), util_1.NullThrowsReasons.MissingToken('union or intersection token', 'duplicate type constituent')); + bracketAfterTokens = sourceCode.getTokensBetween(constituentNode, afterUnionOrIntersectionToken); + bracketBeforeTokens = sourceCode.getTokensBefore(constituentNode, { + count: bracketAfterTokens.length, + }); + } + context.report({ + loc: { + start: constituentNode.loc.start, + end: (bracketAfterTokens.at(-1) ?? constituentNode).loc.end, + }, + node: constituentNode, + messageId, + data, + fix: fixer => [ + beforeUnionOrIntersectionToken, + ...bracketBeforeTokens, + constituentNode, + ...bracketAfterTokens, + afterUnionOrIntersectionToken, + ].flatMap(token => (token ? fixer.remove(token) : [])), + }); + } + function checkDuplicateRecursively(unionOrIntersection, constituentNode, uniqueConstituents, cachedTypeMap, forEachNodeType) { + const type = parserServices.getTypeAtLocation(constituentNode); + if (tsutils.isIntrinsicErrorType(type)) { + return; + } + const duplicatedPrevious = uniqueConstituents.find(ele => isSameAstNode(ele, constituentNode)) ?? + cachedTypeMap.get(type); + if (duplicatedPrevious) { + report('duplicate', constituentNode, { + type: unionOrIntersection, + previous: sourceCode.getText(duplicatedPrevious), + }); + return; + } + forEachNodeType?.(type, constituentNode); + cachedTypeMap.set(type, constituentNode); + uniqueConstituents.push(constituentNode); + if ((unionOrIntersection === 'Union' && + constituentNode.type === utils_1.AST_NODE_TYPES.TSUnionType) || + (unionOrIntersection === 'Intersection' && + constituentNode.type === utils_1.AST_NODE_TYPES.TSIntersectionType)) { + for (const constituent of constituentNode.types) { + checkDuplicateRecursively(unionOrIntersection, constituent, uniqueConstituents, cachedTypeMap, forEachNodeType); + } + } + } function checkDuplicate(node, forEachNodeType) { const cachedTypeMap = new Map(); - node.types.reduce((uniqueConstituents, constituentNode) => { - const constituentNodeType = parserServices.getTypeAtLocation(constituentNode); - if (tsutils.isIntrinsicErrorType(constituentNodeType)) { - return uniqueConstituents; - } - const report = (messageId, data) => { - const getUnionOrIntersectionToken = (where, at) => sourceCode[`getTokens${where}`](constituentNode, { - filter: token => ['&', '|'].includes(token.value), - }).at(at); - const beforeUnionOrIntersectionToken = getUnionOrIntersectionToken('Before', -1); - let afterUnionOrIntersectionToken; - let bracketBeforeTokens; - let bracketAfterTokens; - if (beforeUnionOrIntersectionToken) { - bracketBeforeTokens = sourceCode.getTokensBetween(beforeUnionOrIntersectionToken, constituentNode); - bracketAfterTokens = sourceCode.getTokensAfter(constituentNode, { - count: bracketBeforeTokens.length, - }); - } - else { - afterUnionOrIntersectionToken = (0, util_1.nullThrows)(getUnionOrIntersectionToken('After', 0), util_1.NullThrowsReasons.MissingToken('union or intersection token', 'duplicate type constituent')); - bracketAfterTokens = sourceCode.getTokensBetween(constituentNode, afterUnionOrIntersectionToken); - bracketBeforeTokens = sourceCode.getTokensBefore(constituentNode, { - count: bracketAfterTokens.length, - }); - } - context.report({ - loc: { - start: constituentNode.loc.start, - end: (bracketAfterTokens.at(-1) ?? constituentNode).loc.end, - }, - node: constituentNode, - messageId, - data, - fix: fixer => [ - beforeUnionOrIntersectionToken, - ...bracketBeforeTokens, - constituentNode, - ...bracketAfterTokens, - afterUnionOrIntersectionToken, - ].flatMap(token => (token ? fixer.remove(token) : [])), - }); - }; - const duplicatePrevious = uniqueConstituents.find(ele => isSameAstNode(ele, constituentNode)) ?? cachedTypeMap.get(constituentNodeType); - if (duplicatePrevious) { - report('duplicate', { - type: node.type === utils_1.AST_NODE_TYPES.TSIntersectionType - ? 'Intersection' - : 'Union', - previous: sourceCode.getText(duplicatePrevious), - }); - return uniqueConstituents; - } - forEachNodeType?.(constituentNodeType, report); - cachedTypeMap.set(constituentNodeType, constituentNode); - return [...uniqueConstituents, constituentNode]; - }, []); + const uniqueConstituents = []; + const unionOrIntersection = node.type === utils_1.AST_NODE_TYPES.TSIntersectionType + ? 'Intersection' + : 'Union'; + for (const type of node.types) { + checkDuplicateRecursively(unionOrIntersection, type, uniqueConstituents, cachedTypeMap, forEachNodeType); + } } return { ...(!ignoreIntersections && { - TSIntersectionType: checkDuplicate, + TSIntersectionType(node) { + if (node.parent.type === utils_1.AST_NODE_TYPES.TSIntersectionType) { + return; + } + checkDuplicate(node); + }, }), ...(!ignoreUnions && { - TSUnionType: (node) => checkDuplicate(node, (constituentNodeType, report) => { - const maybeTypeAnnotation = node.parent; - if (maybeTypeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation) { - const maybeIdentifier = maybeTypeAnnotation.parent; - if (maybeIdentifier.type === utils_1.AST_NODE_TYPES.Identifier && - maybeIdentifier.optional) { - const maybeFunction = maybeIdentifier.parent; - if ((0, util_1.isFunctionOrFunctionType)(maybeFunction) && - maybeFunction.params.includes(maybeIdentifier) && - tsutils.isTypeFlagSet(constituentNodeType, ts.TypeFlags.Undefined)) { - report('unnecessary'); + TSUnionType: (node) => { + if (node.parent.type === utils_1.AST_NODE_TYPES.TSUnionType) { + return; + } + checkDuplicate(node, (constituentNodeType, constituentNode) => { + const maybeTypeAnnotation = node.parent; + if (maybeTypeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation) { + const maybeIdentifier = maybeTypeAnnotation.parent; + if (maybeIdentifier.type === utils_1.AST_NODE_TYPES.Identifier && + maybeIdentifier.optional) { + const maybeFunction = maybeIdentifier.parent; + if ((0, util_1.isFunctionOrFunctionType)(maybeFunction) && + maybeFunction.params.includes(maybeIdentifier) && + tsutils.isTypeFlagSet(constituentNodeType, ts.TypeFlags.Undefined)) { + report('unnecessary', constituentNode); + } } } - } - }), + }); + }, }), }; }, diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js.map index 7b2a2bdd28..ae60695660 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-duplicate-type-constituents.js.map @@ -1 +1 @@ -{"version":3,"file":"no-duplicate-type-constituents.js","sourceRoot":"","sources":["../../src/rules/no-duplicate-type-constituents.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"no-duplicate-type-constituents.js","sourceRoot":"","sources":["../../src/rules/no-duplicate-type-constituents.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js index e300fd3e1b..b45bf650d3 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js @@ -86,11 +86,12 @@ exports.default = (0, util_1.createRule)({ else { onlyConstructor = false; if (((prop.type === utils_1.AST_NODE_TYPES.PropertyDefinition || - prop.type === utils_1.AST_NODE_TYPES.MethodDefinition) && + prop.type === utils_1.AST_NODE_TYPES.MethodDefinition || + prop.type === utils_1.AST_NODE_TYPES.AccessorProperty) && !prop.static) || prop.type === utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition || - prop.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition // `static abstract` methods and properties are currently not supported. See: https://github.com/microsoft/TypeScript/issues/34516 - ) { + prop.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition || // `static abstract` methods and properties are currently not supported. See: https://github.com/microsoft/TypeScript/issues/34516 + prop.type === utils_1.AST_NODE_TYPES.TSAbstractAccessorProperty) { onlyStatic = false; } } diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js.map index 0c7adb74d9..366639ee7c 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-extraneous-class.js.map @@ -1 +1 @@ -{"version":3,"file":"no-extraneous-class.js","sourceRoot":"","sources":["../../src/rules/no-extraneous-class.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"no-extraneous-class.js","sourceRoot":"","sources":["../../src/rules/no-extraneous-class.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js index 78d799c9ad..67a839e6a5 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js @@ -190,9 +190,8 @@ exports.default = (0, util_1.createRule)({ return ((0, isTypeImport_1.isTypeImport)(firstDefinition) && isImportDeclaration(firstDefinition.parent) && isExternalModuleDeclarationWithName(scope, firstDefinition.parent.source.value) && - secondDefinition.node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration && - secondDefinition.node.parent.type === - utils_1.AST_NODE_TYPES.ExportNamedDeclaration); + (secondDefinition.node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration || + secondDefinition.node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration)); } /** * Check if variable name is allowed. diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js.map index 969823b245..0446576418 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-shadow.js.map @@ -1 +1 @@ -{"version":3,"file":"no-shadow.js","sourceRoot":"","sources":["../../src/rules/no-shadow.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"no-shadow.js","sourceRoot":"","sources":["../../src/rules/no-shadow.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js index 6ee51a756b..bc23886ffb 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js @@ -38,40 +38,7 @@ const tsutils = __importStar(require("ts-api-utils")); const ts = __importStar(require("typescript")); const util_1 = require("../util"); const assertionFunctionUtils_1 = require("../util/assertionFunctionUtils"); -// Truthiness utilities // #region -const valueIsPseudoBigInt = (value) => { - return typeof value === 'object'; -}; -const getValueOfLiteralType = (type) => { - if (valueIsPseudoBigInt(type.value)) { - return pseudoBigIntToBigInt(type.value); - } - return type.value; -}; -const isTruthyLiteral = (type) => tsutils.isTrueLiteralType(type) || - (type.isLiteral() && !!getValueOfLiteralType(type)); -const isPossiblyFalsy = (type) => tsutils - .unionTypeParts(type) - // Intersections like `string & {}` can also be possibly falsy, - // requiring us to look into the intersection. - .flatMap(type => tsutils.intersectionTypeParts(type)) - // PossiblyFalsy flag includes literal values, so exclude ones that - // are definitely truthy - .filter(t => !isTruthyLiteral(t)) - .some(type => (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.PossiblyFalsy)); -const isPossiblyTruthy = (type) => tsutils - .unionTypeParts(type) - .map(type => tsutils.intersectionTypeParts(type)) - .some(intersectionParts => -// It is possible to define intersections that are always falsy, -// like `"" & { __brand: string }`. -intersectionParts.every(type => !tsutils.isFalsyType(type))); -// Nullish utilities -const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; -const isNullishType = (type) => (0, util_1.isTypeFlagSet)(type, nullishFlag); -const isPossiblyNullish = (type) => tsutils.unionTypeParts(type).some(isNullishType); -const isAlwaysNullish = (type) => tsutils.unionTypeParts(type).every(isNullishType); function toStaticValue(type) { // type.isLiteral() only covers numbers/bigints and strings, hence the rest of the branches. if (tsutils.isBooleanLiteralType(type)) { @@ -84,13 +51,10 @@ function toStaticValue(type) { return { value: null }; } if (type.isLiteral()) { - return { value: getValueOfLiteralType(type) }; + return { value: (0, util_1.getValueOfLiteralType)(type) }; } return undefined; } -function pseudoBigIntToBigInt(value) { - return BigInt((value.negative ? '-' : '') + value.base10Value); -} const BOOL_OPERATORS = new Set([ '<', '>', @@ -283,10 +247,10 @@ exports.default = (0, util_1.createRule)({ if ((0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Never)) { messageId = 'never'; } - else if (!isPossiblyTruthy(type)) { + else if (!(0, util_1.isPossiblyTruthy)(type)) { messageId = !isUnaryNotArgument ? 'alwaysFalsy' : 'alwaysTruthy'; } - else if (!isPossiblyFalsy(type)) { + else if (!(0, util_1.isPossiblyFalsy)(type)) { messageId = !isUnaryNotArgument ? 'alwaysTruthy' : 'alwaysFalsy'; } if (messageId) { @@ -306,7 +270,7 @@ exports.default = (0, util_1.createRule)({ if ((0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Never)) { messageId = 'never'; } - else if (!isPossiblyNullish(type) && + else if (!(0, util_1.isPossiblyNullish)(type) && !(node.type === utils_1.AST_NODE_TYPES.MemberExpression && isNullableMemberExpression(node))) { // Since typescript array index signature types don't represent the @@ -319,7 +283,7 @@ exports.default = (0, util_1.createRule)({ messageId = 'neverNullish'; } } - else if (isAlwaysNullish(type)) { + else if ((0, util_1.isAlwaysNullish)(type)) { messageId = 'alwaysNullish'; } if (messageId) { @@ -479,10 +443,10 @@ exports.default = (0, util_1.createRule)({ (0, util_1.isTypeUnknownType)(constraintType)) { return; } - if (isPossiblyFalsy(constraintType)) { + if ((0, util_1.isPossiblyFalsy)(constraintType)) { hasFalsyReturnTypes = true; } - if (isPossiblyTruthy(constraintType)) { + if ((0, util_1.isPossiblyTruthy)(constraintType)) { hasTruthyReturnTypes = true; } // bail early if both a possibly-truthy and a possibly-falsy have been detected diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js.map index 89e70a1061..2075595c96 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-condition.js.map @@ -1 +1 @@ -{"version":3,"file":"no-unnecessary-condition.js","sourceRoot":"","sources":["../../src/rules/no-unnecessary-condition.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"no-unnecessary-condition.js","sourceRoot":"","sources":["../../src/rules/no-unnecessary-condition.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js index d21571a9fb..6367f2b0a4 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js @@ -62,200 +62,284 @@ exports.default = (0, util_1.createRule)({ defaultOptions: [], create(context) { const services = (0, util_1.getParserServices)(context); - function isUnderlyingTypeString(expression) { - const checker = services.program.getTypeChecker(); - const { constraintType } = (0, util_1.getConstraintInfo)(checker, services.getTypeAtLocation(expression)); - if (constraintType == null) { - return false; - } - const isString = (t) => { - return (0, util_1.isTypeFlagSet)(t, ts.TypeFlags.StringLike); - }; - if (constraintType.isUnion()) { - return constraintType.types.every(isString); + const checker = services.program.getTypeChecker(); + function isStringLike(type) { + return (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.StringLike); + } + function isUnderlyingTypeString(type) { + if (type.isUnion()) { + return type.types.every(isStringLike); } - if (constraintType.isIntersection()) { - return constraintType.types.some(isString); + if (type.isIntersection()) { + return type.types.some(isStringLike); } - return isString(constraintType); + return isStringLike(type); } - function isLiteral(expression) { - return expression.type === utils_1.AST_NODE_TYPES.Literal; + /** + * Checks for whole enum types, i.e. `MyEnum`, and not their values, i.e. `MyEnum.A` + */ + function isEnumType(type) { + const symbol = type.getSymbol(); + return !!(symbol?.valueDeclaration && + ts.isEnumDeclaration(symbol.valueDeclaration)); } - function isTemplateLiteral(expression) { - return expression.type === utils_1.AST_NODE_TYPES.TemplateLiteral; + const isLiteral = (0, util_1.isNodeOfType)(utils_1.TSESTree.AST_NODE_TYPES.Literal); + function isTemplateLiteral(node) { + return node.type === utils_1.AST_NODE_TYPES.TemplateLiteral; } - function isInfinityIdentifier(expression) { - return (expression.type === utils_1.AST_NODE_TYPES.Identifier && - expression.name === 'Infinity'); + function isInfinityIdentifier(node) { + return (node.type === utils_1.AST_NODE_TYPES.Identifier && node.name === 'Infinity'); } - function isNaNIdentifier(expression) { - return (expression.type === utils_1.AST_NODE_TYPES.Identifier && - expression.name === 'NaN'); + function isNaNIdentifier(node) { + return node.type === utils_1.AST_NODE_TYPES.Identifier && node.name === 'NaN'; + } + function isFixableIdentifier(node) { + return ((0, util_1.isUndefinedIdentifier)(node) || + isInfinityIdentifier(node) || + isNaNIdentifier(node)); } function hasCommentsBetweenQuasi(startQuasi, endQuasi) { const startToken = (0, util_1.nullThrows)(context.sourceCode.getTokenByRangeStart(startQuasi.range[0]), util_1.NullThrowsReasons.MissingToken('`${', 'opening template literal')); const endToken = (0, util_1.nullThrows)(context.sourceCode.getTokenByRangeStart(endQuasi.range[0]), util_1.NullThrowsReasons.MissingToken('}', 'closing template literal')); return context.sourceCode.commentsExistBetween(startToken, endToken); } - return { - TemplateLiteral(node) { - if (node.parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression) { - return; - } - const hasSingleStringVariable = node.quasis.length === 2 && - node.quasis[0].value.raw === '' && - node.quasis[1].value.raw === '' && - node.expressions.length === 1 && - isUnderlyingTypeString(node.expressions[0]); - if (hasSingleStringVariable) { - if (hasCommentsBetweenQuasi(node.quasis[0], node.quasis[1])) { - return; - } - context.report({ - loc: (0, rangeToLoc_1.rangeToLoc)(context.sourceCode, [ - node.expressions[0].range[0] - 2, - node.expressions[0].range[1] + 1, - ]), - messageId: 'noUnnecessaryTemplateExpression', - fix(fixer) { - const wrappingCode = (0, util_1.getMovedNodeCode)({ - destinationNode: node, - nodeToMove: node.expressions[0], - sourceCode: context.sourceCode, - }); - return fixer.replaceText(node, wrappingCode); - }, + function isTrivialInterpolation(node) { + return (node.quasis.length === 2 && + node.quasis[0].value.raw === '' && + node.quasis[1].value.raw === ''); + } + function getInterpolations(node) { + if (node.type === utils_1.AST_NODE_TYPES.TemplateLiteral) { + return node.expressions; + } + return node.types; + } + function getInterpolationInfos(node) { + return getInterpolations(node).map((interpolation, index) => ({ + interpolation, + nextQuasi: node.quasis[index + 1], + prevQuasi: node.quasis[index], + })); + } + function getLiteral(node) { + const maybeLiteral = node.type === utils_1.AST_NODE_TYPES.TSLiteralType ? node.literal : node; + return isLiteral(maybeLiteral) ? maybeLiteral : null; + } + function getTemplateLiteral(node) { + const maybeTemplateLiteral = node.type === utils_1.AST_NODE_TYPES.TSLiteralType ? node.literal : node; + return isTemplateLiteral(maybeTemplateLiteral) + ? maybeTemplateLiteral + : null; + } + function reportSingleInterpolation(node) { + const interpolations = getInterpolations(node); + context.report({ + loc: (0, rangeToLoc_1.rangeToLoc)(context.sourceCode, [ + interpolations[0].range[0] - 2, + interpolations[0].range[1] + 1, + ]), + messageId: 'noUnnecessaryTemplateExpression', + fix(fixer) { + const wrappingCode = (0, util_1.getMovedNodeCode)({ + destinationNode: node, + nodeToMove: interpolations[0], + sourceCode: context.sourceCode, }); - return; + return fixer.replaceText(node, wrappingCode); + }, + }); + } + function isUnncessaryValueInterpolation({ interpolation, nextQuasi, prevQuasi, }) { + if (hasCommentsBetweenQuasi(prevQuasi, nextQuasi)) { + return false; + } + if (isFixableIdentifier(interpolation)) { + return true; + } + if (isLiteral(interpolation)) { + // allow trailing whitespace literal + if (startsWithNewLine(nextQuasi.value.raw)) { + return !(typeof interpolation.value === 'string' && + isWhitespace(interpolation.value)); } - const fixableExpressionsReversed = node.expressions - .map((expression, index) => ({ - expression, - nextQuasi: node.quasis[index + 1], - prevQuasi: node.quasis[index], - })) - .filter(({ expression, nextQuasi, prevQuasi }) => { - if ((0, util_1.isUndefinedIdentifier)(expression) || - isInfinityIdentifier(expression) || - isNaNIdentifier(expression)) { - return true; - } - // allow expressions that include comments - if (hasCommentsBetweenQuasi(prevQuasi, nextQuasi)) { - return false; - } - if (isLiteral(expression)) { - // allow trailing whitespace literal - if (startsWithNewLine(nextQuasi.value.raw)) { - return !(typeof expression.value === 'string' && - isWhitespace(expression.value)); - } - return true; - } - if (isTemplateLiteral(expression)) { - // allow trailing whitespace literal - if (startsWithNewLine(nextQuasi.value.raw)) { - return !(expression.quasis.length === 1 && - isWhitespace(expression.quasis[0].value.raw)); - } - return true; - } - return false; - }) - .reverse(); - let nextCharacterIsOpeningCurlyBrace = false; - for (const { expression, nextQuasi, prevQuasi, } of fixableExpressionsReversed) { - const fixers = []; - if (nextQuasi.value.raw !== '') { - nextCharacterIsOpeningCurlyBrace = - nextQuasi.value.raw.startsWith('{'); - } - if (isLiteral(expression)) { - let escapedValue = (typeof expression.value === 'string' - ? // The value is already a string, so we're removing quotes: - // "'va`lue'" -> "va`lue" - expression.raw.slice(1, -1) - : // The value may be one of number | bigint | boolean | RegExp | null. - // In regular expressions, we escape every backslash - String(expression.value).replaceAll('\\', '\\\\')) - // The string or RegExp may contain ` or ${. - // We want both of these to be escaped in the final template expression. - // - // A pair of backslashes means "escaped backslash", so backslashes - // from this pair won't escape ` or ${. Therefore, to escape these - // sequences in the resulting template expression, we need to escape - // all sequences that are preceded by an even number of backslashes. - // - // This RegExp does the following transformations: - // \` -> \` - // \\` -> \\\` - // \${ -> \${ - // \\${ -> \\\${ - .replaceAll(new RegExp(`${String(evenNumOfBackslashesRegExp.source)}(\`|\\\${)`, 'g'), '\\$1'); - // `...${'...$'}{...` - // ^^^^ - if (nextCharacterIsOpeningCurlyBrace && - endsWithUnescapedDollarSign(escapedValue)) { - escapedValue = escapedValue.replaceAll(/\$$/g, '\\$'); - } - if (escapedValue.length !== 0) { - nextCharacterIsOpeningCurlyBrace = escapedValue.startsWith('{'); - } - fixers.push(fixer => [fixer.replaceText(expression, escapedValue)]); - } - else if (isTemplateLiteral(expression)) { - // Since we iterate from the last expression to the first, - // a subsequent expression can tell the current expression - // that it starts with {. + return true; + } + if (isTemplateLiteral(interpolation)) { + // allow trailing whitespace literal + if (startsWithNewLine(nextQuasi.value.raw)) { + return !(interpolation.quasis.length === 1 && + isWhitespace(interpolation.quasis[0].value.raw)); + } + return true; + } + return false; + } + function isUnncessaryTypeInterpolation({ interpolation, nextQuasi, prevQuasi, }) { + if (hasCommentsBetweenQuasi(prevQuasi, nextQuasi)) { + return false; + } + const literal = getLiteral(interpolation); + if (literal) { + // allow trailing whitespace literal + if (startsWithNewLine(nextQuasi.value.raw)) { + return !(typeof literal.value === 'string' && isWhitespace(literal.value)); + } + return true; + } + if (interpolation.type === utils_1.AST_NODE_TYPES.TSNullKeyword || + interpolation.type === utils_1.AST_NODE_TYPES.TSUndefinedKeyword) { + return true; + } + const templateLiteral = getTemplateLiteral(interpolation); + if (templateLiteral) { + // allow trailing whitespace literal + if (startsWithNewLine(nextQuasi.value.raw)) { + return !(templateLiteral.quasis.length === 1 && + isWhitespace(templateLiteral.quasis[0].value.raw)); + } + return true; + } + return false; + } + function getReportDescriptors(infos) { + let nextCharacterIsOpeningCurlyBrace = false; + const reportDescriptors = []; + const reversedInfos = [...infos].reverse(); + for (const { interpolation, nextQuasi, prevQuasi } of reversedInfos) { + const fixers = []; + if (nextQuasi.value.raw !== '') { + nextCharacterIsOpeningCurlyBrace = + nextQuasi.value.raw.startsWith('{'); + } + const literal = getLiteral(interpolation); + const templateLiteral = getTemplateLiteral(interpolation); + if (literal) { + let escapedValue = (typeof literal.value === 'string' + ? // The value is already a string, so we're removing quotes: + // "'va`lue'" -> "va`lue" + literal.raw.slice(1, -1) + : // The value may be one of number | bigint | boolean | RegExp | null. + // In regular expressions, we escape every backslash + String(literal.value).replaceAll('\\', '\\\\')) + // The string or RegExp may contain ` or ${. + // We want both of these to be escaped in the final template expression. // - // `... ${`... $`}${'{...'} ...` - // ^ ^ subsequent expression starts with { - // current expression ends with a dollar sign, - // so '$' + '{' === '${' (bad news for us). - // Let's escape the dollar sign at the end. - if (nextCharacterIsOpeningCurlyBrace && - endsWithUnescapedDollarSign(expression.quasis[expression.quasis.length - 1].value.raw)) { - fixers.push(fixer => [ - fixer.replaceTextRange([expression.range[1] - 2, expression.range[1] - 2], '\\'), - ]); - } - if (expression.quasis.length === 1 && - expression.quasis[0].value.raw.length !== 0) { - nextCharacterIsOpeningCurlyBrace = - expression.quasis[0].value.raw.startsWith('{'); - } - // Remove the beginning and trailing backtick characters. - fixers.push(fixer => [ - fixer.removeRange([expression.range[0], expression.range[0] + 1]), - fixer.removeRange([expression.range[1] - 1, expression.range[1]]), - ]); + // A pair of backslashes means "escaped backslash", so backslashes + // from this pair won't escape ` or ${. Therefore, to escape these + // sequences in the resulting template expression, we need to escape + // all sequences that are preceded by an even number of backslashes. + // + // This RegExp does the following transformations: + // \` -> \` + // \\` -> \\\` + // \${ -> \${ + // \\${ -> \\\${ + .replaceAll(new RegExp(`${String(evenNumOfBackslashesRegExp.source)}(\`|\\\${)`, 'g'), '\\$1'); + // `...${'...$'}{...` + // ^^^^ + if (nextCharacterIsOpeningCurlyBrace && + endsWithUnescapedDollarSign(escapedValue)) { + escapedValue = escapedValue.replaceAll(/\$$/g, '\\$'); } - else { - nextCharacterIsOpeningCurlyBrace = false; + if (escapedValue.length !== 0) { + nextCharacterIsOpeningCurlyBrace = escapedValue.startsWith('{'); } - // `... $${'{...'} ...` - // ^^^^^ + fixers.push(fixer => [fixer.replaceText(literal, escapedValue)]); + } + else if (templateLiteral) { + // Since we iterate from the last expression to the first, + // a subsequent expression can tell the current expression + // that it starts with {. + // + // `... ${`... $`}${'{...'} ...` + // ^ ^ subsequent expression starts with { + // current expression ends with a dollar sign, + // so '$' + '{' === '${' (bad news for us). + // Let's escape the dollar sign at the end. if (nextCharacterIsOpeningCurlyBrace && - endsWithUnescapedDollarSign(prevQuasi.value.raw)) { + endsWithUnescapedDollarSign(templateLiteral.quasis[templateLiteral.quasis.length - 1].value + .raw)) { fixers.push(fixer => [ - fixer.replaceTextRange([prevQuasi.range[1] - 3, prevQuasi.range[1] - 2], '\\$'), + fixer.replaceTextRange([templateLiteral.range[1] - 2, templateLiteral.range[1] - 2], '\\'), ]); } - const warnLocStart = prevQuasi.range[1] - 2; - const warnLocEnd = nextQuasi.range[0] + 1; - context.report({ - loc: (0, rangeToLoc_1.rangeToLoc)(context.sourceCode, [warnLocStart, warnLocEnd]), - messageId: 'noUnnecessaryTemplateExpression', - fix(fixer) { - return [ - // Remove the quasis' parts that are related to the current expression. - fixer.removeRange([warnLocStart, expression.range[0]]), - fixer.removeRange([expression.range[1], warnLocEnd]), - ...fixers.flatMap(cb => cb(fixer)), - ]; - }, - }); + if (templateLiteral.quasis.length === 1 && + templateLiteral.quasis[0].value.raw.length !== 0) { + nextCharacterIsOpeningCurlyBrace = + templateLiteral.quasis[0].value.raw.startsWith('{'); + } + // Remove the beginning and trailing backtick characters. + fixers.push(fixer => [ + fixer.removeRange([ + templateLiteral.range[0], + templateLiteral.range[0] + 1, + ]), + fixer.removeRange([ + templateLiteral.range[1] - 1, + templateLiteral.range[1], + ]), + ]); + } + else { + nextCharacterIsOpeningCurlyBrace = false; + } + // `... $${'{...'} ...` + // ^^^^^ + if (nextCharacterIsOpeningCurlyBrace && + endsWithUnescapedDollarSign(prevQuasi.value.raw)) { + fixers.push(fixer => [ + fixer.replaceTextRange([prevQuasi.range[1] - 3, prevQuasi.range[1] - 2], '\\$'), + ]); + } + const warnLocStart = prevQuasi.range[1] - 2; + const warnLocEnd = nextQuasi.range[0] + 1; + reportDescriptors.push({ + loc: (0, rangeToLoc_1.rangeToLoc)(context.sourceCode, [warnLocStart, warnLocEnd]), + messageId: 'noUnnecessaryTemplateExpression', + fix(fixer) { + return [ + // Remove the quasis' parts that are related to the current expression. + fixer.removeRange([warnLocStart, interpolation.range[0]]), + fixer.removeRange([interpolation.range[1], warnLocEnd]), + ...fixers.flatMap(cb => cb(fixer)), + ]; + }, + }); + } + return reportDescriptors; + } + return { + TemplateLiteral(node) { + if (node.parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression) { + return; + } + if (isTrivialInterpolation(node) && + !hasCommentsBetweenQuasi(node.quasis[0], node.quasis[1])) { + const { constraintType } = (0, util_1.getConstraintInfo)(checker, services.getTypeAtLocation(node.expressions[0])); + if (constraintType && isUnderlyingTypeString(constraintType)) { + reportSingleInterpolation(node); + return; + } + } + const infos = getInterpolationInfos(node).filter(isUnncessaryValueInterpolation); + for (const reportDescriptor of getReportDescriptors(infos)) { + context.report(reportDescriptor); + } + }, + TSTemplateLiteralType(node) { + if (isTrivialInterpolation(node) && + !hasCommentsBetweenQuasi(node.quasis[0], node.quasis[1])) { + const { constraintType } = (0, util_1.getConstraintInfo)(checker, services.getTypeAtLocation(node.types[0])); + if (constraintType && + isUnderlyingTypeString(constraintType) && + !isEnumType(constraintType)) { + reportSingleInterpolation(node); + return; + } + } + const infos = getInterpolationInfos(node).filter(isUnncessaryTypeInterpolation); + for (const reportDescriptor of getReportDescriptors(infos)) { + context.report(reportDescriptor); } }, }; diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js.map index 463ad7d18a..f42b625769 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/no-unnecessary-template-expression.js.map @@ -1 +1 @@ -{"version":3,"file":"no-unnecessary-template-expression.js","sourceRoot":"","sources":["../../src/rules/no-unnecessary-template-expression.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"no-unnecessary-template-expression.js","sourceRoot":"","sources":["../../src/rules/no-unnecessary-template-expression.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js index 9a43492826..345e284047 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js @@ -37,6 +37,10 @@ const utils_1 = require("@typescript-eslint/utils"); const tsutils = __importStar(require("ts-api-utils")); const ts = __importStar(require("typescript")); const util_1 = require("../util"); +const isIdentifierOrMemberExpression = (0, util_1.isNodeOfTypes)([ + utils_1.AST_NODE_TYPES.Identifier, + utils_1.AST_NODE_TYPES.MemberExpression, +]); exports.default = (0, util_1.createRule)({ name: 'prefer-nullish-coalescing', meta: { @@ -144,23 +148,16 @@ exports.default = (0, util_1.createRule)({ messageId: 'noStrictNullCheck', }); } - // todo: rename to something more specific? - function checkAssignmentOrLogicalExpression(node, description, equals) { - const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = checker.getTypeAtLocation(tsNode.left); - if (!(0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined)) { - return; + /** + * Checks whether a type tested for truthiness is eligible for conversion to + * a nullishness check, taking into account the rule's configuration. + */ + function isTypeEligibleForPreferNullish(type) { + if (!(0, util_1.isPossiblyNullish)(type)) { + return false; } - if (ignoreConditionalTests === true && isConditionalTest(node)) { - return; - } - if (ignoreMixedLogicalExpressions === true && - isMixedLogicalExpression(node)) { - return; - } - // https://github.com/typescript-eslint/typescript-eslint/issues/5439 - /* eslint-disable @typescript-eslint/no-non-null-assertion */ const ignorableFlags = [ + /* eslint-disable @typescript-eslint/no-non-null-assertion */ (ignorePrimitives === true || ignorePrimitives.bigint) && ts.TypeFlags.BigIntLike, (ignorePrimitives === true || ignorePrimitives.boolean) && @@ -169,6 +166,7 @@ exports.default = (0, util_1.createRule)({ ts.TypeFlags.NumberLike, (ignorePrimitives === true || ignorePrimitives.string) && ts.TypeFlags.StringLike, + /* eslint-enable @typescript-eslint/no-non-null-assertion */ ] .filter((flag) => typeof flag === 'number') .reduce((previous, flag) => previous | flag, 0); @@ -177,9 +175,46 @@ exports.default = (0, util_1.createRule)({ type.types.some(t => tsutils .intersectionTypeParts(t) .some(t => tsutils.isTypeFlagSet(t, ignorableFlags)))) { + return false; + } + return true; + } + /** + * Determines whether a control flow construct that uses the truthiness of + * a test expression is eligible for conversion to the nullish coalescing + * operator, taking into account (both dependent on the rule's configuration): + * 1. Whether the construct is in a permitted syntactic context + * 2. Whether the type of the test expression is deemed eligible for + * conversion + * + * @param node The overall node to be converted (e.g. `a || b` or `a ? a : b`) + * @param testNode The node being tested (i.e. `a`) + */ + function isTruthinessCheckEligibleForPreferNullish({ node, testNode, }) { + const testType = parserServices.getTypeAtLocation(testNode); + if (!isTypeEligibleForPreferNullish(testType)) { + return false; + } + if (ignoreConditionalTests === true && isConditionalTest(node)) { + return false; + } + if (ignoreBooleanCoercion === true && + isBooleanConstructorContext(node, context)) { + return false; + } + return true; + } + function checkAndFixWithPreferNullishOverOr(node, description, equals) { + if (!isTruthinessCheckEligibleForPreferNullish({ + node, + testNode: node.left, + })) { + return; + } + if (ignoreMixedLogicalExpressions === true && + isMixedLogicalExpression(node)) { return; } - /* eslint-enable @typescript-eslint/no-non-null-assertion */ const barBarOperator = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(node.left, token => token.type === utils_1.AST_TOKEN_TYPES.Punctuator && token.value === node.operator), util_1.NullThrowsReasons.MissingToken('operator', node.type)); function* fix(fixer) { @@ -211,7 +246,7 @@ exports.default = (0, util_1.createRule)({ } return { 'AssignmentExpression[operator = "||="]'(node) { - checkAssignmentOrLogicalExpression(node, 'assignment', '='); + checkAndFixWithPreferNullishOverOr(node, 'assignment', '='); }, ConditionalExpression(node) { if (ignoreTernaryTests) { @@ -266,60 +301,79 @@ exports.default = (0, util_1.createRule)({ } } } + let identifierOrMemberExpression; + let hasTruthinessCheck = false; + let hasNullCheckWithoutTruthinessCheck = false; + let hasUndefinedCheckWithoutTruthinessCheck = false; if (!operator) { - return; - } - let identifier; - let hasUndefinedCheck = false; - let hasNullCheck = false; - // we check that the test only contains null, undefined and the identifier - for (const testNode of nodesInsideTestExpression) { - if ((0, util_1.isNullLiteral)(testNode)) { - hasNullCheck = true; - } - else if ((0, util_1.isUndefinedIdentifier)(testNode)) { - hasUndefinedCheck = true; - } - else if ((operator === '!==' || operator === '!=') && - (0, util_1.isNodeEqual)(testNode, node.consequent)) { - identifier = testNode; + hasTruthinessCheck = true; + if (isIdentifierOrMemberExpression(node.test) && + (0, util_1.isNodeEqual)(node.test, node.consequent)) { + identifierOrMemberExpression = node.test; } - else if ((operator === '===' || operator === '==') && - (0, util_1.isNodeEqual)(testNode, node.alternate)) { - identifier = testNode; + else if (node.test.type === utils_1.AST_NODE_TYPES.UnaryExpression && + node.test.operator === '!' && + isIdentifierOrMemberExpression(node.test.argument) && + (0, util_1.isNodeEqual)(node.test.argument, node.alternate)) { + identifierOrMemberExpression = node.test.argument; + operator = '!'; } - else { - return; + } + else { + // we check that the test only contains null, undefined and the identifier + for (const testNode of nodesInsideTestExpression) { + if ((0, util_1.isNullLiteral)(testNode)) { + hasNullCheckWithoutTruthinessCheck = true; + } + else if ((0, util_1.isUndefinedIdentifier)(testNode)) { + hasUndefinedCheckWithoutTruthinessCheck = true; + } + else if ((operator === '!==' || operator === '!=') && + (0, util_1.isNodeEqual)(testNode, node.consequent)) { + identifierOrMemberExpression = testNode; + } + else if ((operator === '===' || operator === '==') && + (0, util_1.isNodeEqual)(testNode, node.alternate)) { + identifierOrMemberExpression = testNode; + } } } - if (!identifier) { + if (!identifierOrMemberExpression) { return; } - const isFixable = (() => { + const isFixableWithPreferNullishOverTernary = (() => { + // x ? x : y and !x ? y : x patterns + if (hasTruthinessCheck) { + return isTruthinessCheckEligibleForPreferNullish({ + node, + testNode: identifierOrMemberExpression, + }); + } + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(identifierOrMemberExpression); + const type = checker.getTypeAtLocation(tsNode); + const flags = (0, util_1.getTypeFlags)(type); // it is fixable if we check for both null and undefined, or not if neither - if (hasUndefinedCheck === hasNullCheck) { - return hasUndefinedCheck; + if (hasUndefinedCheckWithoutTruthinessCheck === + hasNullCheckWithoutTruthinessCheck) { + return hasUndefinedCheckWithoutTruthinessCheck; } // it is fixable if we loosely check for either null or undefined if (operator === '==' || operator === '!=') { return true; } - const tsNode = parserServices.esTreeNodeToTSNodeMap.get(identifier); - const type = checker.getTypeAtLocation(tsNode); - const flags = (0, util_1.getTypeFlags)(type); if (flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { return false; } const hasNullType = (flags & ts.TypeFlags.Null) !== 0; // it is fixable if we check for undefined and the type is not nullable - if (hasUndefinedCheck && !hasNullType) { + if (hasUndefinedCheckWithoutTruthinessCheck && !hasNullType) { return true; } const hasUndefinedType = (flags & ts.TypeFlags.Undefined) !== 0; // it is fixable if we check for null and the type can't be undefined - return hasNullCheck && !hasUndefinedType; + return hasNullCheckWithoutTruthinessCheck && !hasUndefinedType; })(); - if (isFixable) { + if (isFixableWithPreferNullishOverTernary) { context.report({ node, messageId: 'preferNullishOverTernary', @@ -330,9 +384,9 @@ exports.default = (0, util_1.createRule)({ messageId: 'suggestNullish', data: { equals: '' }, fix(fixer) { - const [left, right] = operator === '===' || operator === '==' - ? [node.alternate, node.consequent] - : [node.consequent, node.alternate]; + const [left, right] = operator === '===' || operator === '==' || operator === '!' + ? [identifierOrMemberExpression, node.consequent] + : [identifierOrMemberExpression, node.alternate]; return fixer.replaceText(node, `${(0, util_1.getTextWithParentheses)(context.sourceCode, left)} ?? ${(0, util_1.getTextWithParentheses)(context.sourceCode, right)}`); }, }, @@ -341,11 +395,7 @@ exports.default = (0, util_1.createRule)({ } }, 'LogicalExpression[operator = "||"]'(node) { - if (ignoreBooleanCoercion === true && - isBooleanConstructorContext(node, context)) { - return; - } - checkAssignmentOrLogicalExpression(node, 'or', ''); + checkAndFixWithPreferNullishOverOr(node, 'or', ''); }, }; }, diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js.map index d37329c2d8..c4dad6ff28 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-nullish-coalescing.js.map @@ -1 +1 @@ -{"version":3,"file":"prefer-nullish-coalescing.js","sourceRoot":"","sources":["../../src/rules/prefer-nullish-coalescing.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prefer-nullish-coalescing.js","sourceRoot":"","sources":["../../src/rules/prefer-nullish-coalescing.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js index 6c28dca17a..9749fb038c 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js @@ -138,6 +138,26 @@ exports.default = (0, util_1.createRule)({ nameNode: services.tsNodeToESTreeNodeMap.get(violatingNode.name), }; } + function getTypeAnnotationForViolatingNode(node, type, initializerType) { + const annotation = checker.typeToString(type); + // verify the about-to-be-added type annotation is in-scope + if (tsutils.isTypeFlagSet(initializerType, ts.TypeFlags.EnumLiteral)) { + const scope = context.sourceCode.getScope(node); + const variable = utils_1.ASTUtils.findVariable(scope, annotation); + if (variable == null) { + return null; + } + const definition = variable.defs.find(def => def.isTypeDefinition); + if (definition == null) { + return null; + } + const definitionType = services.getTypeAtLocation(definition.node); + if (definitionType !== type) { + return null; + } + } + return annotation; + } return { [`${functionScopeBoundaries}:exit`](node) { if (utils_1.ASTUtils.isConstructor(node)) { @@ -168,13 +188,45 @@ exports.default = (0, util_1.createRule)({ return { node: esNode }; } })(); + const typeAnnotation = (() => { + if (esNode.type !== utils_1.AST_NODE_TYPES.PropertyDefinition) { + return null; + } + if (esNode.typeAnnotation || !esNode.value) { + return null; + } + if (nameNode.type !== utils_1.AST_NODE_TYPES.Identifier) { + return null; + } + const hasConstructorModifications = finalizedClassScope.memberHasConstructorModifications(nameNode.name); + if (!hasConstructorModifications) { + return null; + } + const violatingType = services.getTypeAtLocation(esNode); + const initializerType = services.getTypeAtLocation(esNode.value); + // if the RHS is a literal, its type would be narrowed, while the + // type of the initializer (which isn't `readonly`) would be the + // widened type + if (initializerType === violatingType) { + return null; + } + if (!tsutils.isLiteralType(initializerType)) { + return null; + } + return getTypeAnnotationForViolatingNode(esNode, violatingType, initializerType); + })(); context.report({ ...reportNodeOrLoc, messageId: 'preferReadonly', data: { name: context.sourceCode.getText(nameNode), }, - fix: fixer => fixer.insertTextBefore(nameNode, 'readonly '), + *fix(fixer) { + yield fixer.insertTextBefore(nameNode, 'readonly '); + if (typeAnnotation) { + yield fixer.insertTextAfter(nameNode, `: ${typeAnnotation}`); + } + }, }); } }, @@ -210,6 +262,7 @@ class ClassScope { classType; constructorScopeDepth = OUTSIDE_CONSTRUCTOR; memberVariableModifications = new Set(); + memberVariableWithConstructorModifications = new Set(); privateModifiableMembers = new Map(); privateModifiableStatics = new Map(); staticVariableModifications = new Set(); @@ -250,6 +303,7 @@ class ClassScope { const relationOfModifierTypeToClass = this.getTypeToClassRelation(modifierType); if (relationOfModifierTypeToClass === TypeToClassRelation.Instance && this.constructorScopeDepth === DIRECTLY_INSIDE_CONSTRUCTOR) { + this.memberVariableWithConstructorModifications.add(node.name.text); return; } if (relationOfModifierTypeToClass === TypeToClassRelation.Instance || @@ -332,5 +386,8 @@ class ClassScope { } return TypeToClassRelation.Instance; } + memberHasConstructorModifications(name) { + return this.memberVariableWithConstructorModifications.has(name); + } } //# sourceMappingURL=prefer-readonly.js.map \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js.map index 1e2541c01e..e8f0813fc0 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-readonly.js.map @@ -1 +1 @@ -{"version":3,"file":"prefer-readonly.js","sourceRoot":"","sources":["../../src/rules/prefer-readonly.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prefer-readonly.js","sourceRoot":"","sources":["../../src/rules/prefer-readonly.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/util/getValueOfLiteralType.js b/node_modules/@typescript-eslint/eslint-plugin/dist/util/getValueOfLiteralType.js new file mode 100644 index 0000000000..0c96475dd0 --- /dev/null +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/util/getValueOfLiteralType.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getValueOfLiteralType = void 0; +const valueIsPseudoBigInt = (value) => { + return typeof value === 'object'; +}; +const pseudoBigIntToBigInt = (value) => { + return BigInt((value.negative ? '-' : '') + value.base10Value); +}; +const getValueOfLiteralType = (type) => { + if (valueIsPseudoBigInt(type.value)) { + return pseudoBigIntToBigInt(type.value); + } + return type.value; +}; +exports.getValueOfLiteralType = getValueOfLiteralType; +//# sourceMappingURL=getValueOfLiteralType.js.map \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/util/getValueOfLiteralType.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/util/getValueOfLiteralType.js.map new file mode 100644 index 0000000000..a00c40abb7 --- /dev/null +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/util/getValueOfLiteralType.js.map @@ -0,0 +1 @@ +{"version":3,"file":"getValueOfLiteralType.js","sourceRoot":"","sources":["../../src/util/getValueOfLiteralType.ts"],"names":[],"mappings":";;;AAEA,MAAM,mBAAmB,GAAG,CAC1B,KAAwC,EACd,EAAE;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,KAAsB,EAAU,EAAE;IAC9D,OAAO,MAAM,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;AACjE,CAAC,CAAC;AAEK,MAAM,qBAAqB,GAAG,CACnC,IAAoB,EACM,EAAE;IAC5B,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC;AACpB,CAAC,CAAC;AAPW,QAAA,qBAAqB,yBAOhC"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js b/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js index 42a74159ad..8214b47cd2 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js @@ -40,6 +40,8 @@ __exportStar(require("./needsToBeAwaited"), exports); __exportStar(require("./scopeUtils"), exports); __exportStar(require("./types"), exports); __exportStar(require("./getConstraintInfo"), exports); +__exportStar(require("./getValueOfLiteralType"), exports); +__exportStar(require("./truthinessAndNullishUtils"), exports); // this is done for convenience - saves migrating all of the old rules __exportStar(require("@typescript-eslint/type-utils"), exports); exports.applyDefault = utils_1.ESLintUtils.applyDefault, exports.deepMerge = utils_1.ESLintUtils.deepMerge, exports.getParserServices = utils_1.ESLintUtils.getParserServices, exports.isObjectNotArray = utils_1.ESLintUtils.isObjectNotArray, exports.nullThrows = utils_1.ESLintUtils.nullThrows, exports.NullThrowsReasons = utils_1.ESLintUtils.NullThrowsReasons; diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js.map index 5f9fe1914e..7acefad5e3 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/util/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oDAAuD;AAEvD,6CAA2B;AAC3B,2DAAyC;AACzC,+CAA6B;AAC7B,oDAAkC;AAClC,uDAAqC;AACrC,0DAAwC;AACxC,yDAAuC;AACvC,oDAAkC;AAClC,2DAAyC;AACzC,sDAAoC;AACpC,qDAAmC;AACnC,mEAAiD;AACjD,+CAA6B;AAC7B,gDAA8B;AAC9B,kDAAgC;AAChC,iEAA+C;AAC/C,0DAAwC;AACxC,yCAAuB;AACvB,4DAA0C;AAC1C,oDAAkC;AAClC,qDAAmC;AACnC,+CAA6B;AAC7B,0CAAwB;AACxB,sDAAoC;AAEpC,sEAAsE;AACtE,gEAA8C;AAG5C,oBAAY,GAMV,mBAAW,eALb,iBAAS,GAKP,mBAAW,YAJb,yBAAiB,GAIf,mBAAW,oBAHb,wBAAgB,GAGd,mBAAW,mBAFb,kBAAU,GAER,mBAAW,aADb,yBAAiB,GACf,mBAAW,mBAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oDAAuD;AAEvD,6CAA2B;AAC3B,2DAAyC;AACzC,+CAA6B;AAC7B,oDAAkC;AAClC,uDAAqC;AACrC,0DAAwC;AACxC,yDAAuC;AACvC,oDAAkC;AAClC,2DAAyC;AACzC,sDAAoC;AACpC,qDAAmC;AACnC,mEAAiD;AACjD,+CAA6B;AAC7B,gDAA8B;AAC9B,kDAAgC;AAChC,iEAA+C;AAC/C,0DAAwC;AACxC,yCAAuB;AACvB,4DAA0C;AAC1C,oDAAkC;AAClC,qDAAmC;AACnC,+CAA6B;AAC7B,0CAAwB;AACxB,sDAAoC;AACpC,0DAAwC;AACxC,8DAA4C;AAE5C,sEAAsE;AACtE,gEAA8C;AAG5C,oBAAY,GAMV,mBAAW,eALb,iBAAS,GAKP,mBAAW,YAJb,yBAAiB,GAIf,mBAAW,oBAHb,wBAAgB,GAGd,mBAAW,mBAFb,kBAAU,GAER,mBAAW,aADb,yBAAiB,GACf,mBAAW,mBAAC"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/util/truthinessAndNullishUtils.js b/node_modules/@typescript-eslint/eslint-plugin/dist/util/truthinessAndNullishUtils.js new file mode 100644 index 0000000000..a4bf84ff8c --- /dev/null +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/util/truthinessAndNullishUtils.js @@ -0,0 +1,68 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isAlwaysNullish = exports.isPossiblyNullish = exports.isPossiblyTruthy = exports.isPossiblyFalsy = void 0; +const tsutils = __importStar(require("ts-api-utils")); +const ts = __importStar(require("typescript")); +const getValueOfLiteralType_1 = require("./getValueOfLiteralType"); +// Truthiness utilities +const isTruthyLiteral = (type) => tsutils.isTrueLiteralType(type) || + (type.isLiteral() && !!(0, getValueOfLiteralType_1.getValueOfLiteralType)(type)); +const isPossiblyFalsy = (type) => tsutils + .unionTypeParts(type) + // Intersections like `string & {}` can also be possibly falsy, + // requiring us to look into the intersection. + .flatMap(type => tsutils.intersectionTypeParts(type)) + // PossiblyFalsy flag includes literal values, so exclude ones that + // are definitely truthy + .filter(t => !isTruthyLiteral(t)) + .some(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); +exports.isPossiblyFalsy = isPossiblyFalsy; +const isPossiblyTruthy = (type) => tsutils + .unionTypeParts(type) + .map(type => tsutils.intersectionTypeParts(type)) + .some(intersectionParts => +// It is possible to define intersections that are always falsy, +// like `"" & { __brand: string }`. +intersectionParts.every(type => !tsutils.isFalsyType(type))); +exports.isPossiblyTruthy = isPossiblyTruthy; +// Nullish utilities +const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; +const isNullishType = (type) => tsutils.isTypeFlagSet(type, nullishFlag); +const isPossiblyNullish = (type) => tsutils.unionTypeParts(type).some(isNullishType); +exports.isPossiblyNullish = isPossiblyNullish; +const isAlwaysNullish = (type) => tsutils.unionTypeParts(type).every(isNullishType); +exports.isAlwaysNullish = isAlwaysNullish; +//# sourceMappingURL=truthinessAndNullishUtils.js.map \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/util/truthinessAndNullishUtils.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/util/truthinessAndNullishUtils.js.map new file mode 100644 index 0000000000..edf93ccad6 --- /dev/null +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/util/truthinessAndNullishUtils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"truthinessAndNullishUtils.js","sourceRoot":"","sources":["../../src/util/truthinessAndNullishUtils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,sDAAwC;AACxC,+CAAiC;AAEjC,mEAAgE;AAEhE,uBAAuB;AACvB,MAAM,eAAe,GAAG,CAAC,IAAa,EAAW,EAAE,CACjD,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC;IAC/B,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,IAAA,6CAAqB,EAAC,IAAI,CAAC,CAAC,CAAC;AAE/C,MAAM,eAAe,GAAG,CAAC,IAAa,EAAW,EAAE,CACxD,OAAO;KACJ,cAAc,CAAC,IAAI,CAAC;IACrB,+DAA+D;IAC/D,8CAA8C;KAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACrD,mEAAmE;IACnE,wBAAwB;KACvB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;KAChC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;AAT9D,QAAA,eAAe,mBAS+C;AAEpE,MAAM,gBAAgB,GAAG,CAAC,IAAa,EAAW,EAAE,CACzD,OAAO;KACJ,cAAc,CAAC,IAAI,CAAC;KACpB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;KAChD,IAAI,CAAC,iBAAiB,CAAC,EAAE;AACxB,gEAAgE;AAChE,mCAAmC;AACnC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAC5D,CAAC;AARO,QAAA,gBAAgB,oBAQvB;AAEN,oBAAoB;AACpB,MAAM,WAAW,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;AAC/D,MAAM,aAAa,GAAG,CAAC,IAAa,EAAW,EAAE,CAC/C,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AAEpC,MAAM,iBAAiB,GAAG,CAAC,IAAa,EAAW,EAAE,CAC1D,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AADtC,QAAA,iBAAiB,qBACqB;AAE5C,MAAM,eAAe,GAAG,CAAC,IAAa,EAAW,EAAE,CACxD,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;AADvC,QAAA,eAAe,mBACwB"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/consistent-type-imports.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/consistent-type-imports.mdx index 3f7dc32004..4ff5054917 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/consistent-type-imports.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/consistent-type-imports.mdx @@ -107,8 +107,8 @@ The rule will **_not_** report any errors in files _that contain decorators_ whe > See [Blog > Changes to consistent-type-imports when used with legacy decorators and decorator metadata](/blog/changes-to-consistent-type-imports-with-decorators) for more details. -If you are using [type-aware linting](https://typescript-eslint.io/linting/typed-linting) then we will automatically infer your setup from your tsconfig and you should not need to configure anything. -Otherwise you can explicitly tell our tooling to analyze your code as if the compiler option was turned on by setting both [`parserOptions.emitDecoratorMetadata = true`](https://typescript-eslint.io/packages/parser/#emitdecoratormetadata) and [`parserOptions.experimentalDecorators = true`](https://typescript-eslint.io/packages/parser/#experimentaldecorators). +If you are using [type-aware linting](/getting-started/typed-linting) then we will automatically infer your setup from your tsconfig and you should not need to configure anything. +Otherwise you can explicitly tell our tooling to analyze your code as if the compiler option was turned on by setting both [`parserOptions.emitDecoratorMetadata = true`](/packages/parser/#emitdecoratormetadata) and [`parserOptions.experimentalDecorators = true`](/packages/parser/#experimentaldecorators). ## Comparison with `importsNotUsedAsValues` / `verbatimModuleSyntax` diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-explicit-any.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-explicit-any.mdx index 33b382920b..f0c8c20c6d 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-explicit-any.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-explicit-any.mdx @@ -162,6 +162,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) - [`no-unsafe-argument`](./no-unsafe-argument.mdx) - [`no-unsafe-assignment`](./no-unsafe-assignment.mdx) - [`no-unsafe-call`](./no-unsafe-call.mdx) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-namespace.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-namespace.mdx index 8e7ca864a8..7a4928f491 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-namespace.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-namespace.mdx @@ -135,8 +135,15 @@ declare module 'foo' {} ## When Not To Use It -If your project was architected before modern modules and namespaces, it may be difficult to migrate off of namespaces. +If your project uses TypeScript's CommonJS export syntax (`export = ...`), you may need to use namespaces in order to export types from your module. +You can learn more about this at: + +- [TypeScript#52203](https://github.com/microsoft/TypeScript/pull/52203), the pull request introducing [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) +- [TypeScript#60852](https://github.com/microsoft/TypeScript/issues/60852), an issue requesting syntax to export types from a CommonJS module. + +If your project uses this syntax, either because it was architected before modern modules and namespaces, or because a module option such as `verbatimModuleSyntax` requires it, it may be difficult to migrate off of namespaces. In that case you may not be able to use this rule for parts of your project. + You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. ## Further Reading @@ -144,6 +151,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates {/* cspell:disable-next-line */} - [FAQ: I get errors from the `@typescript-eslint/no-namespace` and/or `no-var` rules about declaring global variables](/troubleshooting/faqs/eslint#i-get-errors-from-the-typescript-eslintno-namespace-andor-no-var-rules-about-declaring-global-variables) -- [Modules](https://www.typescriptlang.org/docs/handbook/modules.html) -- [Namespaces](https://www.typescriptlang.org/docs/handbook/namespaces.html) -- [Namespaces and Modules](https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html) +- [FAQ: How should I handle reports that conflict with verbatimModuleSyntax?](/troubleshooting/faqs/typescript#how-should-i-handle-reports-that-conflict-with-verbatimmodulesyntax) +- [TypeScript handbook entry on Modules](https://www.typescriptlang.org/docs/handbook/modules.html) +- [TypeScript handbook entry on Namespaces](https://www.typescriptlang.org/docs/handbook/namespaces.html) +- [TypeScript handbook entry on Namespaces and Modules](https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-require-imports.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-require-imports.mdx index 1d4fd9ea7b..1d82851b1e 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-require-imports.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-require-imports.mdx @@ -9,7 +9,9 @@ import TabItem from '@theme/TabItem'; > > See **https://typescript-eslint.io/rules/no-require-imports** for documentation. -Prefer the newer ES6-style imports over `require()`. +Depending on your TSConfig settings and whether you're authoring ES Modules or CommonJS, TS may allow both `import` and `require()` to be used, even within a single file. + +This rule enforces that you use the newer ES Module `import` syntax over CommonJS `require()`. ## Examples @@ -42,7 +44,7 @@ import * as lib3 from 'lib3'; These strings will be compiled into regular expressions with the `u` flag and be used to test against the imported path. A common use case is to allow importing `package.json`. This is because `package.json` commonly lives outside of the TS root directory, so statically importing it would lead to root directory conflicts, especially with `resolveJsonModule` enabled. You can also use it to allow importing any JSON if your environment doesn't support JSON modules, or use it for other cases where `import` statements cannot work. -With `{allow: ['/package\\.json$']}`: +With `{ allow: ['/package\\.json$'] }`: @@ -66,9 +68,9 @@ console.log(require('../package.json').version); {/* insert option description */} When set to `true`, `import ... = require(...)` declarations won't be reported. -This is useful if you use certain module options that require strict CommonJS interop semantics. +This is beneficial if you use certain module options that require strict CommonJS interop semantics, such as [verbatimModuleSyntax](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax). -With `{allowAsImport: true}`: +With `{ allowAsImport: true }`: @@ -90,10 +92,22 @@ import foo from 'foo'; +## Usage with CommonJS + +While this rule is primarily intended to promote ES Module syntax, it still makes sense to enable this rule when authoring CommonJS modules. + +If you prefer to use TypeScript's built-in `import ... from ...` ES Module syntax, which is transformed to `require()` calls during transpilation when outputting CommonJS, you can use the rule's default behavior. + +If, instead, you prefer to use `require()` syntax, we recommend you use this rule with [`allowAsImport`](#allowAsImport) enabled. +That way, you still enforce usage of `import ... = require(...)` rather than bare `require()` calls, which are not statically analyzed by TypeScript. +We don't directly a way to _prohibit_ ES Module syntax from being used; consider instead using TypeScript's [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) option if you find yourself in a situation where you would want this. + ## When Not To Use It -If your project frequently uses older CommonJS `require`s, then this rule might not be applicable to you. -If only a subset of your project uses `require`s then you might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. +If you are authoring CommonJS modules _and_ your project frequently uses dynamic `require`s, then this rule might not be applicable to you. +Otherwise the `allowAsImport` option probably suits your needs. + +If only a subset of your project uses dynamic `require`s then you might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. ## Related To diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unnecessary-template-expression.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unnecessary-template-expression.mdx index 1fe39d412d..c720652ebf 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unnecessary-template-expression.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unnecessary-template-expression.mdx @@ -28,6 +28,8 @@ The new name is a drop-in replacement with identical functionality. const ab1 = `${'a'}${'b'}`; const ab2 = `a${'b'}`; +type AB1 = `${'A'}${'B'}`; +type AB2 = `A${'B'}`; const stringWithNumber = `${'1 + 1 = '}${2}`; @@ -38,9 +40,13 @@ const stringWithBoolean = `${'true is '}${true}`; const text = 'a'; const wrappedText = `${text}`; +type Text = 'A'; +type WrappedText = `${Text}`; declare const intersectionWithString: string & { _brand: 'test-brand' }; const wrappedIntersection = `${intersectionWithString}`; +type IntersectionWithString = string & { _brand: 'test-brand' }; +type WrappedIntersection = `${IntersectionWithString}`; ``` @@ -51,6 +57,15 @@ const wrappedIntersection = `${intersectionWithString}`; const ab1 = `ab`; const ab2 = `ab`; +type AB = `AB`; + +// Transforming enum members into string unions using template literals is allowed. +enum ABC { + A = 'A', + B = 'B', + C = 'C', +} +type ABCUnion = `${ABC}`; const stringWithNumber = `1 + 1 = 2`; @@ -61,9 +76,13 @@ const stringWithBoolean = `true is true`; const text = 'a'; const wrappedText = text; +type Text = 'A'; +type WrappedText = Text; declare const intersectionWithString: string & { _brand: 'test-brand' }; const wrappedIntersection = intersectionWithString; +type IntersectionWithString = string & { _brand: 'test-brand' }; +type WrappedIntersection = IntersectionWithString; ``` diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-argument.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-argument.mdx index 696bc4c551..09b98cb29e 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-argument.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-argument.mdx @@ -90,6 +90,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) - [`no-explicit-any`](./no-explicit-any.mdx) - [`no-unsafe-assignment`](./no-unsafe-assignment.mdx) - [`no-unsafe-call`](./no-unsafe-call.mdx) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-assignment.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-assignment.mdx index 84a1d0ee47..dceab88bb8 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-assignment.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-assignment.mdx @@ -93,6 +93,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) - [`no-explicit-any`](./no-explicit-any.mdx) - [`no-unsafe-argument`](./no-unsafe-argument.mdx) - [`no-unsafe-call`](./no-unsafe-call.mdx) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-call.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-call.mdx index 540d464de8..961749b62e 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-call.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-call.mdx @@ -112,6 +112,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) - [`no-explicit-any`](./no-explicit-any.mdx) - [`no-unsafe-argument`](./no-unsafe-argument.mdx) - [`no-unsafe-assignment`](./no-unsafe-assignment.mdx) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-function-type.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-function-type.mdx index ee1a84395d..e6cd3a03c1 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-function-type.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-function-type.mdx @@ -58,6 +58,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) - [`no-empty-object-type`](./no-empty-object-type.mdx) - [`no-restricted-types`](./no-restricted-types.mdx) - [`no-unsafe-call`](./no-unsafe-call.mdx) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-member-access.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-member-access.mdx index 4b41fb56ba..2f1eb0edbf 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-member-access.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-member-access.mdx @@ -73,6 +73,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) - [`no-explicit-any`](./no-explicit-any.mdx) - [`no-unsafe-argument`](./no-unsafe-argument.mdx) - [`no-unsafe-assignment`](./no-unsafe-assignment.mdx) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-return.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-return.mdx index 74e86e07e1..013c14b31d 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-return.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unsafe-return.mdx @@ -118,6 +118,7 @@ You might consider using [ESLint disable comments](https://eslint.org/docs/lates ## Related To +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) - [`no-explicit-any`](./no-explicit-any.mdx) - [`no-unsafe-argument`](./no-unsafe-argument.mdx) - [`no-unsafe-assignment`](./no-unsafe-assignment.mdx) diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unused-vars.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unused-vars.mdx index 0e4fab226a..01a8a62012 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unused-vars.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/no-unused-vars.mdx @@ -12,7 +12,11 @@ import TabItem from '@theme/TabItem'; This rule extends the base [`eslint/no-unused-vars`](https://eslint.org/docs/rules/no-unused-vars) rule. It adds support for TypeScript features, such as types. -## Benefits Over TypeScript +## Options + +## FAQs + +### What benefits does this rule have over TypeScript? TypeScript provides [`noUnusedLocals`](https://www.typescriptlang.org/tsconfig#noUnusedLocals) and [`noUnusedParameters`](https://www.typescriptlang.org/tsconfig#noUnusedParameters) compiler options that can report errors on unused local variables or parameters, respectively. Those compiler options can be convenient to use if you don't want to set up ESLint and typescript-eslint. @@ -52,3 +56,66 @@ Also see similar rules provided by ESLint: - [`no-unused-private-class-members`](https://eslint.org/docs/latest/rules/no-unused-private-class-members) - [`no-unused-labels`](https://eslint.org/docs/latest/rules/no-unused-labels) + +### Why does this rule report variables used only for types? + +This rule does not count type-only uses when determining whether a variable is used. +Declaring variables only to use them for types adds code and runtime complexity. +The variables are never actually used at runtime. +They can be misleading to readers of the code. + + + + + +For example, if a variable is only used for `typeof`, this rule will report: + +```ts +const box = { + // ~~~ + // 'box' is assigned a value but only used as a type. + value: 123, +}; + +export type Box = typeof box; +``` + +Instead, it's often cleaner and less code to write out the types directly: + +```ts +export interface Box { + value: number; +} +``` + + + + + +For example, if a Zod schema variable is only used for `typeof`, this rule will report: + +```ts +import { z } from 'zod'; + +const schema = z.object({ + // ~~~~~~ + // 'schema' is assigned a value but only used as a type. + value: z.number(), +}); + +export type Box = z.infer; +``` + +Instead, it's often cleaner and less code to write out the types directly: + +```ts +export interface Box { + value: number; +} +``` + + + + + +If you find yourself writing runtime values only for types, consider refactoring your code to declare types directly. diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-nullish-coalescing.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-nullish-coalescing.mdx index d5742e1a87..be44bfe11d 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-nullish-coalescing.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-nullish-coalescing.mdx @@ -16,6 +16,7 @@ This rule reports when you may consider replacing: - An `||` operator with `??` - An `||=` operator with `??=` +- Ternary expressions (`?:`) that are equivalent to `||` or `??` with `??` :::caution This rule will not work as expected if [`strictNullChecks`](https://www.typescriptlang.org/tsconfig#strictNullChecks) is not enabled. @@ -42,7 +43,9 @@ foo === undefined ? 'a string' : foo; const foo: string | null = 'bar'; foo !== null ? foo : 'a string'; +foo ? foo : 'a string'; foo === null ? 'a string' : foo; +!foo ? 'a string' : foo; ``` Correct code for `ignoreTernaryTests: false`: @@ -61,6 +64,8 @@ foo ?? 'a string'; const foo: string | null = 'bar'; foo ?? 'a string'; foo ?? 'a string'; +foo ?? 'a string'; +foo ?? 'a string'; ``` ### `ignoreConditionalTests` diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/use-unknown-in-catch-callback-variable.mdx b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/use-unknown-in-catch-callback-variable.mdx index b7423b2d1d..72a1fd8665 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/use-unknown-in-catch-callback-variable.mdx +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/use-unknown-in-catch-callback-variable.mdx @@ -91,3 +91,7 @@ For further reading on this, you may also want to look into If your codebase is not yet able to enable `useUnknownInCatchVariables`, it likely would be similarly difficult to enable this rule. If you have modified the global type declarations in order to make `then()` and `catch()` callbacks use the `unknown` type without an explicit type annotation, you do not need this rule. + +## Related To + +- [Avoiding `any`s with Linting and TypeScript](/blog/avoiding-anys) diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager/package.json b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager/package.json index 451de1fb7b..c957046031 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager/package.json +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/scope-manager", - "version": "8.21.0", + "version": "8.22.0", "description": "TypeScript scope analyser for ESLint", "files": [ "dist", @@ -46,13 +46,13 @@ "typecheck": "npx nx typecheck" }, "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "devDependencies": { "@jest/types": "29.6.3", "@types/glob": "*", - "@typescript-eslint/typescript-estree": "8.21.0", + "@typescript-eslint/typescript-estree": "8.22.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts index cb2f5eb3a0..98c88337c7 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts @@ -51,6 +51,7 @@ export interface ParserOptions { experimentalDecorators?: boolean; extraFileExtensions?: string[]; filePath?: string; + isolatedDeclarations?: boolean; jsDocParsingMode?: JSDocParsingMode; jsxFragmentName?: string | null; jsxPragma?: string | null; diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map index 2c9b2b945a..b049b68e67 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"parser-options.d.ts","sourceRoot":"","sources":["../src/parser-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,CAAC,QAAQ,GAAG,YAAY,GAAG,mBAAmB,CAAC,EAAE,CAAC;AACtD,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvD,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,SAAS,CAAC;AAEd,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;OAMG;IACH,+DAA+D,CAAC,EAAE,MAAM,CAAC;CAC1E;AAGD,MAAM,WAAW,aAAa;IAC5B,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,aAAa,CAAC,EAAE;QACd,IAAI,CAAC,EAAE,oBAAoB,CAAC;KAC7B,CAAC;IAGF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EACT;QACE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QACnC,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KAC3B,GACD,SAAS,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,CAAC;IAG1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,2CAA2C,CAAC,EAAE,OAAO,CAAC;IAEtD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7C,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,cAAc,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,kCAAkC,CAAC,EAAE,OAAO,CAAC;CAC9C"} \ No newline at end of file +{"version":3,"file":"parser-options.d.ts","sourceRoot":"","sources":["../src/parser-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,CAAC,QAAQ,GAAG,YAAY,GAAG,mBAAmB,CAAC,EAAE,CAAC;AACtD,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvD,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,SAAS,CAAC;AAEd,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;OAMG;IACH,+DAA+D,CAAC,EAAE,MAAM,CAAC;CAC1E;AAGD,MAAM,WAAW,aAAa;IAC5B,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,aAAa,CAAC,EAAE;QACd,IAAI,CAAC,EAAE,oBAAoB,CAAC;KAC7B,CAAC;IAGF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EACT;QACE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QACnC,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KAC3B,GACD,SAAS,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,CAAC;IAG1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,2CAA2C,CAAC,EAAE,OAAO,CAAC;IAEtD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7C,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,cAAc,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,kCAAkC,CAAC,EAAE,OAAO,CAAC;CAC9C"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/package.json b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/package.json index 703d1f50b7..c6c8359d15 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/package.json +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/types", - "version": "8.21.0", + "version": "8.22.0", "description": "Types for the TypeScript-ESTree AST spec", "files": [ "dist", diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map index 69157f2614..2cdc2b585f 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"createParserServices.d.ts","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,IAAI,GACzB,cAAc,CA2BhB"} \ No newline at end of file +{"version":3,"file":"createParserServices.d.ts","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,IAAI,GACzB,cAAc,CA6BhB"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js index 2c5e60c8d2..028cfc78f9 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js @@ -6,6 +6,7 @@ function createParserServices(astMaps, program) { return { emitDecoratorMetadata: undefined, experimentalDecorators: undefined, + isolatedDeclarations: undefined, program, // we always return the node maps because // (a) they don't require type info and @@ -20,6 +21,7 @@ function createParserServices(astMaps, program) { // not set in the config is the same as off emitDecoratorMetadata: compilerOptions.emitDecoratorMetadata ?? false, experimentalDecorators: compilerOptions.experimentalDecorators ?? false, + isolatedDeclarations: compilerOptions.isolatedDeclarations ?? false, ...astMaps, getSymbolAtLocation: node => checker.getSymbolAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)), getTypeAtLocation: node => checker.getTypeAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)), diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map index 54a84fefd4..b2e440f068 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map @@ -1 +1 @@ -{"version":3,"file":"createParserServices.js","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":";;AAKA,oDA8BC;AA9BD,SAAgB,oBAAoB,CAClC,OAAgB,EAChB,OAA0B;IAE1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,qBAAqB,EAAE,SAAS;YAChC,sBAAsB,EAAE,SAAS;YACjC,OAAO;YACP,yCAAyC;YACzC,uCAAuC;YACvC,mFAAmF;YACnF,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAErD,OAAO;QACL,OAAO;QACP,2CAA2C;QAC3C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB,IAAI,KAAK;QACrE,sBAAsB,EAAE,eAAe,CAAC,sBAAsB,IAAI,KAAK;QACvE,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAC1B,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtE,iBAAiB,EAAE,IAAI,CAAC,EAAE,CACxB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"} \ No newline at end of file +{"version":3,"file":"createParserServices.js","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":";;AAKA,oDAgCC;AAhCD,SAAgB,oBAAoB,CAClC,OAAgB,EAChB,OAA0B;IAE1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,qBAAqB,EAAE,SAAS;YAChC,sBAAsB,EAAE,SAAS;YACjC,oBAAoB,EAAE,SAAS;YAC/B,OAAO;YACP,yCAAyC;YACzC,uCAAuC;YACvC,mFAAmF;YACnF,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAErD,OAAO;QACL,OAAO;QACP,2CAA2C;QAC3C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB,IAAI,KAAK;QACrE,sBAAsB,EAAE,eAAe,CAAC,sBAAsB,IAAI,KAAK;QACvE,oBAAoB,EAAE,eAAe,CAAC,oBAAoB,IAAI,KAAK;QACnE,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAC1B,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtE,iBAAiB,EAAE,IAAI,CAAC,EAAE,CACxB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts index 307ab20bce..3136639bf0 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts +++ b/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts @@ -189,6 +189,7 @@ export interface ParserWeakMapESTreeToTSNode checker.getSymbolAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)), getTypeAtLocation: node => checker.getTypeAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)), diff --git a/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map b/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map index 54a84fefd4..b2e440f068 100644 --- a/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map +++ b/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map @@ -1 +1 @@ -{"version":3,"file":"createParserServices.js","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":";;AAKA,oDA8BC;AA9BD,SAAgB,oBAAoB,CAClC,OAAgB,EAChB,OAA0B;IAE1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,qBAAqB,EAAE,SAAS;YAChC,sBAAsB,EAAE,SAAS;YACjC,OAAO;YACP,yCAAyC;YACzC,uCAAuC;YACvC,mFAAmF;YACnF,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAErD,OAAO;QACL,OAAO;QACP,2CAA2C;QAC3C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB,IAAI,KAAK;QACrE,sBAAsB,EAAE,eAAe,CAAC,sBAAsB,IAAI,KAAK;QACvE,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAC1B,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtE,iBAAiB,EAAE,IAAI,CAAC,EAAE,CACxB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"} \ No newline at end of file +{"version":3,"file":"createParserServices.js","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":";;AAKA,oDAgCC;AAhCD,SAAgB,oBAAoB,CAClC,OAAgB,EAChB,OAA0B;IAE1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,qBAAqB,EAAE,SAAS;YAChC,sBAAsB,EAAE,SAAS;YACjC,oBAAoB,EAAE,SAAS;YAC/B,OAAO;YACP,yCAAyC;YACzC,uCAAuC;YACvC,mFAAmF;YACnF,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAErD,OAAO;QACL,OAAO;QACP,2CAA2C;QAC3C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB,IAAI,KAAK;QACrE,sBAAsB,EAAE,eAAe,CAAC,sBAAsB,IAAI,KAAK;QACvE,oBAAoB,EAAE,eAAe,CAAC,oBAAoB,IAAI,KAAK;QACnE,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAC1B,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtE,iBAAiB,EAAE,IAAI,CAAC,EAAE,CACxB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts b/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts index 307ab20bce..3136639bf0 100644 --- a/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts +++ b/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts @@ -189,6 +189,7 @@ export interface ParserWeakMapESTreeToTSNode=4.8.4 <5.8.0" }, "dependencies": { - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/typescript-estree": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4" }, "devDependencies": { diff --git a/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.d.ts.map b/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.d.ts.map index 2a0a12a52a..79548e164d 100644 --- a/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.d.ts.map +++ b/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"TypeOrValueSpecifier.d.ts","sourceRoot":"","sources":["../src/TypeOrValueSpecifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAStC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,CAAC;IAEZ;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAEhB;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,aAAa,GACb,YAAY,GACZ,gBAAgB,CAAC;AAErB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6FR,CAAC;AAEjC,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,SAAS,EAAE,oBAAoB,EAC/B,OAAO,EAAE,EAAE,CAAC,OAAO,GAClB,OAAO,CA4BT;AAED,eAAO,MAAM,wBAAwB,SAC7B,EAAE,CAAC,IAAI,cACD,oBAAoB,EAAE,uBACzB,EAAE,CAAC,OAAO,KAClB,OAC2E,CAAC"} \ No newline at end of file +{"version":3,"file":"TypeOrValueSpecifier.d.ts","sourceRoot":"","sources":["../src/TypeOrValueSpecifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAStC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,CAAC;IAEZ;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAEhB;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,aAAa,GACb,YAAY,GACZ,gBAAgB,CAAC;AAErB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6FR,CAAC;AAEjC,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,SAAS,EAAE,oBAAoB,EAC/B,OAAO,EAAE,EAAE,CAAC,OAAO,GAClB,OAAO,CA6CT;AAED,eAAO,MAAM,wBAAwB,SAC7B,EAAE,CAAC,IAAI,cACD,oBAAoB,EAAE,uBACzB,EAAE,CAAC,OAAO,KAClB,OAC2E,CAAC"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js b/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js index a504970875..15f604bf8c 100644 --- a/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js +++ b/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js @@ -135,26 +135,38 @@ exports.typeOrValueSpecifiersSchema = { type: 'array', }; function typeMatchesSpecifier(type, specifier, program) { - if (tsutils.isIntrinsicErrorType(type)) { - return false; + const wholeTypeMatches = (() => { + if (tsutils.isIntrinsicErrorType(type)) { + return false; + } + if (typeof specifier === 'string') { + return (0, specifierNameMatches_1.specifierNameMatches)(type, specifier); + } + if (!(0, specifierNameMatches_1.specifierNameMatches)(type, specifier.name)) { + return false; + } + const symbol = type.getSymbol() ?? type.aliasSymbol; + const declarations = symbol?.getDeclarations() ?? []; + const declarationFiles = declarations.map(declaration => declaration.getSourceFile()); + switch (specifier.from) { + case 'file': + return (0, typeDeclaredInFile_1.typeDeclaredInFile)(specifier.path, declarationFiles, program); + case 'lib': + return (0, typeDeclaredInLib_1.typeDeclaredInLib)(declarationFiles, program); + case 'package': + return (0, typeDeclaredInPackageDeclarationFile_1.typeDeclaredInPackageDeclarationFile)(specifier.package, declarations, declarationFiles, program); + } + })(); + if (wholeTypeMatches) { + return true; } - if (typeof specifier === 'string') { - return (0, specifierNameMatches_1.specifierNameMatches)(type, specifier); - } - if (!(0, specifierNameMatches_1.specifierNameMatches)(type, specifier.name)) { - return false; - } - const symbol = type.getSymbol() ?? type.aliasSymbol; - const declarations = symbol?.getDeclarations() ?? []; - const declarationFiles = declarations.map(declaration => declaration.getSourceFile()); - switch (specifier.from) { - case 'file': - return (0, typeDeclaredInFile_1.typeDeclaredInFile)(specifier.path, declarationFiles, program); - case 'lib': - return (0, typeDeclaredInLib_1.typeDeclaredInLib)(declarationFiles, program); - case 'package': - return (0, typeDeclaredInPackageDeclarationFile_1.typeDeclaredInPackageDeclarationFile)(specifier.package, declarations, declarationFiles, program); + if (tsutils.isIntersectionType(type) && + tsutils + .intersectionTypeParts(type) + .some(part => typeMatchesSpecifier(part, specifier, program))) { + return true; } + return false; } const typeMatchesSomeSpecifier = (type, specifiers = [], program) => specifiers.some(specifier => typeMatchesSpecifier(type, specifier, program)); exports.typeMatchesSomeSpecifier = typeMatchesSomeSpecifier; diff --git a/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js.map b/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js.map index 3b64aecbd2..aca400f704 100644 --- a/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js.map +++ b/node_modules/@typescript-eslint/type-utils/dist/TypeOrValueSpecifier.js.map @@ -1 +1 @@ -{"version":3,"file":"TypeOrValueSpecifier.js","sourceRoot":"","sources":["../src/TypeOrValueSpecifier.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"TypeOrValueSpecifier.js","sourceRoot":"","sources":["../src/TypeOrValueSpecifier.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.d.ts.map b/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.d.ts.map index b206a4d23e..271cfb7ad0 100644 --- a/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.d.ts.map +++ b/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"specifierNameMatches.d.ts","sourceRoot":"","sources":["../../src/typeOrValueSpecifiers/specifierNameMatches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAItC,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,OAAO,CAmBT"} \ No newline at end of file +{"version":3,"file":"specifierNameMatches.d.ts","sourceRoot":"","sources":["../../src/typeOrValueSpecifiers/specifierNameMatches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,EAAE,CAAC,IAAI,EACb,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GACvB,OAAO,CAeT"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js b/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js index ec3730035b..0d305a2583 100644 --- a/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js +++ b/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js @@ -1,40 +1,6 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); Object.defineProperty(exports, "__esModule", { value: true }); exports.specifierNameMatches = specifierNameMatches; -const tsutils = __importStar(require("ts-api-utils")); function specifierNameMatches(type, names) { if (typeof names === 'string') { names = [names]; @@ -46,9 +12,6 @@ function specifierNameMatches(type, names) { if (names.some(item => candidateNames.includes(item))) { return true; } - if (tsutils.isIntersectionType(type)) { - return type.types.some(subType => specifierNameMatches(subType, names)); - } return false; } //# sourceMappingURL=specifierNameMatches.js.map \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js.map b/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js.map index 37726a7a2c..1351dedce4 100644 --- a/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js.map +++ b/node_modules/@typescript-eslint/type-utils/dist/typeOrValueSpecifiers/specifierNameMatches.js.map @@ -1 +1 @@ -{"version":3,"file":"specifierNameMatches.js","sourceRoot":"","sources":["../../src/typeOrValueSpecifiers/specifierNameMatches.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,oDAsBC;AAxBD,sDAAwC;AAExC,SAAgB,oBAAoB,CAClC,IAAa,EACb,KAAwB;IAExB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;IACpD,MAAM,cAAc,GAAG,MAAM;QAC3B,CAAC,CAAC,CAAC,MAAM,CAAC,WAAqB,EAAE,IAAI,CAAC,aAAa,CAAC;QACpD,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAEzB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"} \ No newline at end of file +{"version":3,"file":"specifierNameMatches.js","sourceRoot":"","sources":["../../src/typeOrValueSpecifiers/specifierNameMatches.ts"],"names":[],"mappings":";;AAEA,oDAkBC;AAlBD,SAAgB,oBAAoB,CAClC,IAAa,EACb,KAAwB;IAExB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;IACpD,MAAM,cAAc,GAAG,MAAM;QAC3B,CAAC,CAAC,CAAC,MAAM,CAAC,WAAqB,EAAE,IAAI,CAAC,aAAa,CAAC;QACpD,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAEzB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager/package.json b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager/package.json index 451de1fb7b..c957046031 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager/package.json +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/scope-manager", - "version": "8.21.0", + "version": "8.22.0", "description": "TypeScript scope analyser for ESLint", "files": [ "dist", @@ -46,13 +46,13 @@ "typecheck": "npx nx typecheck" }, "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "devDependencies": { "@jest/types": "29.6.3", "@types/glob": "*", - "@typescript-eslint/typescript-estree": "8.21.0", + "@typescript-eslint/typescript-estree": "8.22.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts index cb2f5eb3a0..98c88337c7 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts @@ -51,6 +51,7 @@ export interface ParserOptions { experimentalDecorators?: boolean; extraFileExtensions?: string[]; filePath?: string; + isolatedDeclarations?: boolean; jsDocParsingMode?: JSDocParsingMode; jsxFragmentName?: string | null; jsxPragma?: string | null; diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map index 2c9b2b945a..b049b68e67 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/dist/parser-options.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"parser-options.d.ts","sourceRoot":"","sources":["../src/parser-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,CAAC,QAAQ,GAAG,YAAY,GAAG,mBAAmB,CAAC,EAAE,CAAC;AACtD,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvD,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,SAAS,CAAC;AAEd,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;OAMG;IACH,+DAA+D,CAAC,EAAE,MAAM,CAAC;CAC1E;AAGD,MAAM,WAAW,aAAa;IAC5B,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,aAAa,CAAC,EAAE;QACd,IAAI,CAAC,EAAE,oBAAoB,CAAC;KAC7B,CAAC;IAGF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EACT;QACE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QACnC,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KAC3B,GACD,SAAS,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,CAAC;IAG1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,2CAA2C,CAAC,EAAE,OAAO,CAAC;IAEtD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7C,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,cAAc,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,kCAAkC,CAAC,EAAE,OAAO,CAAC;CAC9C"} \ No newline at end of file +{"version":3,"file":"parser-options.d.ts","sourceRoot":"","sources":["../src/parser-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,CAAC,QAAQ,GAAG,YAAY,GAAG,mBAAmB,CAAC,EAAE,CAAC;AACtD,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvD,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,CAAC,GACD,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,EAAE,GACF,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,SAAS,CAAC;AAEd,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE/B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;OAMG;IACH,+DAA+D,CAAC,EAAE,MAAM,CAAC;CAC1E;AAGD,MAAM,WAAW,aAAa;IAC5B,CAAC,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,aAAa,CAAC,EAAE;QACd,IAAI,CAAC,EAAE,oBAAoB,CAAC;KAC7B,CAAC;IAGF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EACT;QACE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QACnC,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KAC3B,GACD,SAAS,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,CAAC;IAG1B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,2CAA2C,CAAC,EAAE,OAAO,CAAC;IAEtD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7C,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,cAAc,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,kCAAkC,CAAC,EAAE,OAAO,CAAC;CAC9C"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/package.json b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/package.json index 703d1f50b7..c6c8359d15 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/package.json +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/types", - "version": "8.21.0", + "version": "8.22.0", "description": "Types for the TypeScript-ESTree AST spec", "files": [ "dist", diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map index 69157f2614..2cdc2b585f 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"createParserServices.d.ts","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,IAAI,GACzB,cAAc,CA2BhB"} \ No newline at end of file +{"version":3,"file":"createParserServices.d.ts","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,IAAI,GACzB,cAAc,CA6BhB"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js index 2c5e60c8d2..028cfc78f9 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js @@ -6,6 +6,7 @@ function createParserServices(astMaps, program) { return { emitDecoratorMetadata: undefined, experimentalDecorators: undefined, + isolatedDeclarations: undefined, program, // we always return the node maps because // (a) they don't require type info and @@ -20,6 +21,7 @@ function createParserServices(astMaps, program) { // not set in the config is the same as off emitDecoratorMetadata: compilerOptions.emitDecoratorMetadata ?? false, experimentalDecorators: compilerOptions.experimentalDecorators ?? false, + isolatedDeclarations: compilerOptions.isolatedDeclarations ?? false, ...astMaps, getSymbolAtLocation: node => checker.getSymbolAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)), getTypeAtLocation: node => checker.getTypeAtLocation(astMaps.esTreeNodeToTSNodeMap.get(node)), diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map index 54a84fefd4..b2e440f068 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/createParserServices.js.map @@ -1 +1 @@ -{"version":3,"file":"createParserServices.js","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":";;AAKA,oDA8BC;AA9BD,SAAgB,oBAAoB,CAClC,OAAgB,EAChB,OAA0B;IAE1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,qBAAqB,EAAE,SAAS;YAChC,sBAAsB,EAAE,SAAS;YACjC,OAAO;YACP,yCAAyC;YACzC,uCAAuC;YACvC,mFAAmF;YACnF,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAErD,OAAO;QACL,OAAO;QACP,2CAA2C;QAC3C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB,IAAI,KAAK;QACrE,sBAAsB,EAAE,eAAe,CAAC,sBAAsB,IAAI,KAAK;QACvE,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAC1B,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtE,iBAAiB,EAAE,IAAI,CAAC,EAAE,CACxB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"} \ No newline at end of file +{"version":3,"file":"createParserServices.js","sourceRoot":"","sources":["../src/createParserServices.ts"],"names":[],"mappings":";;AAKA,oDAgCC;AAhCD,SAAgB,oBAAoB,CAClC,OAAgB,EAChB,OAA0B;IAE1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,qBAAqB,EAAE,SAAS;YAChC,sBAAsB,EAAE,SAAS;YACjC,oBAAoB,EAAE,SAAS;YAC/B,OAAO;YACP,yCAAyC;YACzC,uCAAuC;YACvC,mFAAmF;YACnF,GAAG,OAAO;SACX,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAErD,OAAO;QACL,OAAO;QACP,2CAA2C;QAC3C,qBAAqB,EAAE,eAAe,CAAC,qBAAqB,IAAI,KAAK;QACrE,sBAAsB,EAAE,eAAe,CAAC,sBAAsB,IAAI,KAAK;QACvE,oBAAoB,EAAE,eAAe,CAAC,oBAAoB,IAAI,KAAK;QACnE,GAAG,OAAO;QACV,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAC1B,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtE,iBAAiB,EAAE,IAAI,CAAC,EAAE,CACxB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KACrE,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts index 307ab20bce..3136639bf0 100644 --- a/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts +++ b/node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree/dist/parser-options.d.ts @@ -189,6 +189,7 @@ export interface ParserWeakMapESTreeToTSNode { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + isNodeProcess: () => isNodeProcess +}); +module.exports = __toCommonJS(src_exports); +function isNodeProcess() { + if (typeof navigator !== "undefined" && navigator.product === "ReactNative") { + return true; + } + if (typeof process !== "undefined") { + const type = process.type; + if (type === "renderer" || type === "worker") { + return false; + } + return !!(process.versions && process.versions.node); + } + return false; +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + isNodeProcess +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/is-node-process/lib/index.js.map b/node_modules/is-node-process/lib/index.js.map new file mode 100644 index 0000000000..d821ec24e5 --- /dev/null +++ b/node_modules/is-node-process/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Determines if the current process is a Node.js process.\n */\nexport function isNodeProcess(): boolean {\n if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {\n return true\n }\n\n if (typeof process !== 'undefined') {\n // Electron (https://www.electronjs.org/docs/latest/api/process#processtype-readonly)\n const type = (process as any).type\n if (type === 'renderer' || type === 'worker') {\n return false\n }\n\n\n return !!(\n process.versions &&\n process.versions.node\n )\n }\n\n return false\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,SAAS,gBAAyB;AACvC,MAAI,OAAO,cAAc,eAAe,UAAU,YAAY,eAAe;AAC3E,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,YAAY,aAAa;AAElC,UAAM,OAAQ,QAAgB;AAC9B,QAAI,SAAS,cAAc,SAAS,UAAU;AAC5C,aAAO;AAAA,IACT;AAGA,WAAO,CAAC,EACN,QAAQ,YACR,QAAQ,SAAS;AAAA,EAErB;AAEA,SAAO;AACT;","names":[]} \ No newline at end of file diff --git a/node_modules/is-node-process/lib/index.mjs b/node_modules/is-node-process/lib/index.mjs new file mode 100644 index 0000000000..b52bb5bea1 --- /dev/null +++ b/node_modules/is-node-process/lib/index.mjs @@ -0,0 +1,18 @@ +// src/index.ts +function isNodeProcess() { + if (typeof navigator !== "undefined" && navigator.product === "ReactNative") { + return true; + } + if (typeof process !== "undefined") { + const type = process.type; + if (type === "renderer" || type === "worker") { + return false; + } + return !!(process.versions && process.versions.node); + } + return false; +} +export { + isNodeProcess +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/is-node-process/lib/index.mjs.map b/node_modules/is-node-process/lib/index.mjs.map new file mode 100644 index 0000000000..bfdab80740 --- /dev/null +++ b/node_modules/is-node-process/lib/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Determines if the current process is a Node.js process.\n */\nexport function isNodeProcess(): boolean {\n if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {\n return true\n }\n\n if (typeof process !== 'undefined') {\n // Electron (https://www.electronjs.org/docs/latest/api/process#processtype-readonly)\n const type = (process as any).type\n if (type === 'renderer' || type === 'worker') {\n return false\n }\n\n\n return !!(\n process.versions &&\n process.versions.node\n )\n }\n\n return false\n}\n"],"mappings":";AAGO,SAAS,gBAAyB;AACvC,MAAI,OAAO,cAAc,eAAe,UAAU,YAAY,eAAe;AAC3E,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,YAAY,aAAa;AAElC,UAAM,OAAQ,QAAgB;AAC9B,QAAI,SAAS,cAAc,SAAS,UAAU;AAC5C,aAAO;AAAA,IACT;AAGA,WAAO,CAAC,EACN,QAAQ,YACR,QAAQ,SAAS;AAAA,EAErB;AAEA,SAAO;AACT;","names":[]} \ No newline at end of file diff --git a/node_modules/is-node-process/package.json b/node_modules/is-node-process/package.json new file mode 100644 index 0000000000..bdb262ffaf --- /dev/null +++ b/node_modules/is-node-process/package.json @@ -0,0 +1,43 @@ +{ + "name": "is-node-process", + "description": "Reliably determines if the code is running in Node.js", + "version": "1.2.0", + "main": "lib/index.js", + "module": "lib/index.mjs", + "typings": "lib/index.d.ts", + "exports": { + ".": { + "types": "./lib/index.d.ts", + "require": "./lib/index.js", + "default": "./lib/index.mjs" + } + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/mswjs/is-node-process" + }, + "files": [ + "lib" + ], + "devDependencies": { + "@ossjs/release": "^0.5.1", + "@types/jest": "^27.0.0", + "@types/node": "^18.14.0", + "electron": "^19.0.6", + "jest": "^27.0.6", + "playwright": "^1.22.2", + "spectron": "^15.0.0", + "ts-jest": "^27.0.3", + "tsup": "^6.2.3", + "typescript": "^4.3.5" + }, + "scripts": { + "browser": "open test/browser.html", + "electron": "electron test/fixtures/electron.js", + "test": "jest --testPathIgnorePatterns electron.test.ts", + "test:react-native": "cd test/fixtures/react-native && pnpm test", + "build": "tsup", + "release": "release publish" + } +} \ No newline at end of file diff --git a/node_modules/nock/README.md b/node_modules/nock/README.md index 43f1eaaaf4..457dd95c61 100644 --- a/node_modules/nock/README.md +++ b/node_modules/nock/README.md @@ -1,21 +1,11 @@ # Nock [![npm](https://img.shields.io/npm/v/nock.svg)][npmjs] -[![Build Status](https://travis-ci.org/nock/nock.svg)][build] ![Coverage Status](http://img.shields.io/badge/coverage-100%25-brightgreen.svg) [![Backers on Open Collective](https://opencollective.com/nock/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/nock/sponsors/badge.svg)](#sponsors) [npmjs]: https://www.npmjs.com/package/nock -[build]: https://travis-ci.org/nock/nock - -> **Notice** -> -> We have introduced experimental support for fetch. Please share your feedback with us. You can install it by: -> -> ``` -> npm install --save-dev nock@beta -> ``` HTTP server mocking and expectations library for Node.js @@ -694,46 +684,17 @@ You are able to specify the number of milliseconds that your reply should be del ```js nock('http://my.server.com') .get('/') - .delay(2000) // 2 seconds delay will be applied to the response header. + .delay(2000) // 2 seconds delay will be applied to the response body. .reply(200, '') ``` -`delay(1000)` is an alias for `delayConnection(1000).delayBody(0)` -`delay({ head: 1000, body: 2000 })` is an alias for `delayConnection(1000).delayBody(2000)` -Both of which are covered in detail below. - #### Delay the connection -You are able to specify the number of milliseconds that your connection should be idle before it starts to receive the response. - -To simulate a socket timeout, provide a larger value than the timeout setting on the request. - -```js -nock('http://my.server.com') - .get('/') - .delayConnection(2000) // 2 seconds - .reply(200, '') - -req = http.request('http://my.server.com', { timeout: 1000 }) -``` - -Nock emits timeout events almost immediately by comparing the requested connection delay to the timeout parameter passed to `http.request()` or `http.ClientRequest#setTimeout()`. -This allows you to test timeouts without using fake timers or slowing down your tests. -If the client chooses to _not_ take an action (e.g. abort the request), the request and response will continue on as normal, after real clock time has passed. - -##### Technical Details - -Following the `'finish'` event being emitted by `ClientRequest`, Nock will wait for the next event loop iteration before checking if the request has been aborted. -At this point, any connection delay value is compared against any request timeout setting and a [`'timeout'`](https://nodejs.org/api/http.html#http_event_timeout) is emitted when appropriate from the socket and the request objects. -A Node timeout timer is then registered with any connection delay value to delay real time before checking again if the request has been aborted and the [`'response'`](http://nodejs.org/api/http.html#http_event_response) is emitted by the request. - -A similar method, `.socketDelay()` was removed in version 13. It was thought that having two methods so subtlety similar was confusing. -The discussion can be found at https://github.com/nock/nock/pull/1974. +The `delayConnection` method’s behavior of emitting quick timeout events when the connection delay exceeds the request timeout is now deprecated. Please use the `delay` function instead. #### Delay the response body -You are able to specify the number of milliseconds that the response body should be delayed. -This is the time between the headers being received and the body starting to be received. +The `delayBody` is now deprecated. Please use the `delay` function instead. ```js nock('http://my.server.com') @@ -1643,10 +1604,10 @@ It does this by manipulating the modules cache of Node in a way that conflicts w ## Debugging -Nock uses [`debug`](https://github.com/visionmedia/debug), so just run with environmental variable `DEBUG` set to `nock.*`. +Nock uses node internals [`debuglog`](https://nodejs.org/api/util.html#utildebuglogsection-callbackg), so just run with environmental variable `NODE_DEBUG` set to `nock:*`. ```console -user@local$ DEBUG=nock.* node my_test.js +user@local$ NODE_DEBUG=nock:* node my_test.js ``` Each step in the matching process is logged this way and can be useful when determining why a request was not intercepted by Nock. @@ -1660,11 +1621,11 @@ await got('http://example.com/?foo=bar&baz=foz') ``` ```console -user@local$ DEBUG=nock.scope:example.com node my_test.js +user@local$ DEBUG=nock:scope:example.com node my_test.js ... -nock.scope:example.com Interceptor queries: {"foo":"bar"} +1ms -nock.scope:example.com Request queries: {"foo":"bar","baz":"foz"} +0ms -nock.scope:example.com query matching failed +0ms +NOCK:SCOPE:EXAMPLE.COM 103514: Interceptor queries: {"foo":"bar"} +NOCK:SCOPE:EXAMPLE.COM 103514: Request queries: {"foo":"bar","baz":"foz"} +NOCK:SCOPE:EXAMPLE.COM 103514: query matching failed ``` ## Contributing diff --git a/node_modules/nock/lib/back.js b/node_modules/nock/lib/back.js index 4128c0d25e..44aabb2558 100644 --- a/node_modules/nock/lib/back.js +++ b/node_modules/nock/lib/back.js @@ -9,10 +9,9 @@ const { removeAll: cleanAll, } = require('./intercept') const { loadDefs, define } = require('./scope') - +const { back: debug } = require('./debug') const { format } = require('util') const path = require('path') -const debug = require('debug')('nock.back') let _mode = null @@ -78,7 +77,6 @@ function Back(fixtureName, options, nockedFn) { } debug('context:', context) - // If nockedFn is a function then invoke it, otherwise return a promise resolving to nockDone. if (typeof nockedFn === 'function') { nockedFn.call(context, nockDone) diff --git a/node_modules/nock/lib/common.js b/node_modules/nock/lib/common.js index a6f7f766d0..312bf1c260 100644 --- a/node_modules/nock/lib/common.js +++ b/node_modules/nock/lib/common.js @@ -1,9 +1,10 @@ 'use strict' -const debug = require('debug')('nock.common') +const { common: debug } = require('./debug') const timers = require('timers') const url = require('url') const util = require('util') +const http = require('http') /** * Normalizes the request options so that it always has `host` property. @@ -50,82 +51,6 @@ function isUtf8Representable(buffer) { return reconstructedBuffer.equals(buffer) } -// Array where all information about all the overridden requests are held. -let requestOverrides = {} - -/** - * Overrides the current `request` function of `http` and `https` modules with - * our own version which intercepts issues HTTP/HTTPS requests and forwards them - * to the given `newRequest` function. - * - * @param {Function} newRequest - a function handling requests; it accepts four arguments: - * - proto - a string with the overridden module's protocol name (either `http` or `https`) - * - overriddenRequest - the overridden module's request function already bound to module's object - * - options - the options of the issued request - * - callback - the callback of the issued request - */ -function overrideRequests(newRequest) { - debug('overriding requests') - ;['http', 'https'].forEach(function (proto) { - debug('- overriding request for', proto) - - const moduleName = proto // 1 to 1 match of protocol and module is fortunate :) - const module = require(proto) - const overriddenRequest = module.request - const overriddenGet = module.get - - if (requestOverrides[moduleName]) { - throw new Error( - `Module's request already overridden for ${moduleName} protocol.`, - ) - } - - // Store the properties of the overridden request so that it can be restored later on. - requestOverrides[moduleName] = { - module, - request: overriddenRequest, - get: overriddenGet, - } - // https://nodejs.org/api/http.html#http_http_request_url_options_callback - module.request = function (input, options, callback) { - return newRequest(proto, overriddenRequest.bind(module), [ - input, - options, - callback, - ]) - } - // https://nodejs.org/api/http.html#http_http_get_options_callback - module.get = function (input, options, callback) { - const req = newRequest(proto, overriddenGet.bind(module), [ - input, - options, - callback, - ]) - req.end() - return req - } - - debug('- overridden request for', proto) - }) -} - -/** - * Restores `request` function of `http` and `https` modules to values they - * held before they were overridden by us. - */ -function restoreOverriddenRequests() { - debug('restoring requests') - Object.entries(requestOverrides).forEach( - ([proto, { module, request, get }]) => { - debug('- restoring request for', proto) - module.request = request - module.get = get - debug('- restored request for', proto) - }, - ) - requestOverrides = {} -} - /** * In WHATWG URL vernacular, this returns the origin portion of a URL. * However, the port is not included if it's standard and not already present on the host. @@ -621,6 +546,7 @@ function clearTimer(clear, ids) { } function removeAllTimers() { + debug('remove all timers') clearTimer(clearTimeout, timeouts) clearTimer(clearImmediate, immediates) } @@ -653,6 +579,31 @@ function isRequestDestroyed(req) { ) } +/** + * @param {Request} request + */ +function convertFetchRequestToClientRequest(request) { + const url = new URL(request.url) + const options = { + ...urlToOptions(url), + method: request.method, + host: url.hostname, + port: url.port || (url.protocol === 'https:' ? 443 : 80), + path: url.pathname + url.search, + proto: url.protocol.slice(0, -1), + headers: Object.fromEntries(request.headers.entries()), + } + + // By default, Node adds a host header, but for maximum backward compatibility, we are now removing it. + // However, we need to consider leaving the header and fixing the tests. + if (options.headers.host === options.host) { + const { host, ...restHeaders } = options.headers + options.headers = restHeaders + } + + return new http.ClientRequest(options) +} + /** * Returns true if the given value is a plain object and not an Array. * @param {*} value @@ -760,12 +711,11 @@ module.exports = { normalizeClientRequestArgs, normalizeOrigin, normalizeRequestOptions, - overrideRequests, percentDecode, percentEncode, removeAllTimers, - restoreOverriddenRequests, setImmediate, setTimeout, stringifyRequest, + convertFetchRequestToClientRequest, } diff --git a/node_modules/nock/lib/create_response.js b/node_modules/nock/lib/create_response.js new file mode 100644 index 0000000000..fd953ee6ac --- /dev/null +++ b/node_modules/nock/lib/create_response.js @@ -0,0 +1,53 @@ +'use strict' + +const { STATUS_CODES } = require('http') + +/** + * Creates a Fetch API `Response` instance from the given + * `http.IncomingMessage` instance. + * Inspired by: https://github.com/mswjs/interceptors/blob/04152ed914f8041272b6e92ed374216b8177e1b2/src/interceptors/ClientRequest/utils/createResponse.ts#L8 + */ + +/** + * Response status codes for responses that cannot have body. + * @see https://fetch.spec.whatwg.org/#statuses + */ +const responseStatusCodesWithoutBody = [204, 205, 304] + +/** + * @param {import('http').IncomingMessage} message + * @param {AbortSignal} signal + */ +function createResponse(message, signal) { + const responseBodyOrNull = responseStatusCodesWithoutBody.includes( + message.statusCode || 200, + ) + ? null + : new ReadableStream({ + start(controller) { + message.on('data', chunk => controller.enqueue(chunk)) + message.on('end', () => controller.close()) + message.on('error', error => controller.error(error)) + signal.addEventListener('abort', () => message.destroy(signal.reason)) + }, + cancel() { + message.destroy() + }, + }) + + const rawHeaders = new Headers() + for (let i = 0; i < message.rawHeaders.length; i += 2) { + rawHeaders.append(message.rawHeaders[i], message.rawHeaders[i + 1]) + } + + // @mswjs/interceptors supports rawHeaders. https://github.com/mswjs/interceptors/pull/598 + const response = new Response(responseBodyOrNull, { + status: message.statusCode, + statusText: message.statusMessage || STATUS_CODES[message.statusCode], + headers: rawHeaders, + }) + + return response +} + +module.exports = { createResponse } diff --git a/node_modules/nock/lib/debug.js b/node_modules/nock/lib/debug.js new file mode 100644 index 0000000000..080a6f8cb9 --- /dev/null +++ b/node_modules/nock/lib/debug.js @@ -0,0 +1,12 @@ +'use strict' + +const { debuglog } = require('util') + +module.exports.back = debuglog('nock:back') +module.exports.common = debuglog('nock:common') +module.exports.intercept = debuglog('nock:intercept') +module.exports.request_overrider = debuglog('nock:request_overrider') +module.exports.playback_interceptor = debuglog('nock:playback_interceptor') +module.exports.recorder = debuglog('nock:recorder') +module.exports.socket = debuglog('nock:socket') +module.exports.scopeDebuglog = namespace => debuglog(`nock:scope:${namespace}`) diff --git a/node_modules/nock/lib/intercept.js b/node_modules/nock/lib/intercept.js index bcc1319ce9..7c84f8ef85 100644 --- a/node_modules/nock/lib/intercept.js +++ b/node_modules/nock/lib/intercept.js @@ -8,8 +8,20 @@ const { InterceptedRequestRouter } = require('./intercepted_request_router') const common = require('./common') const { inherits } = require('util') const http = require('http') -const debug = require('debug')('nock.intercept') +const { intercept: debug } = require('./debug') const globalEmitter = require('./global_emitter') +const { BatchInterceptor } = require('@mswjs/interceptors') +const { + default: nodeInterceptors, +} = require('@mswjs/interceptors/presets/node') +const { createResponse } = require('./create_response') +const { once } = require('events') + +const interceptor = new BatchInterceptor({ + name: 'nock-interceptor', + interceptors: nodeInterceptors, +}) +let isNockActive = false /** * @name NetConnectNotAllowedError @@ -238,17 +250,6 @@ function removeInterceptor(options) { // (which might or might not be node's original http.ClientRequest) let originalClientRequest -function ErroringClientRequest(error) { - http.OutgoingMessage.call(this) - process.nextTick( - function () { - this.emit('error', error) - }.bind(this), - ) -} - -inherits(ErroringClientRequest, http.ClientRequest) - function overrideClientRequest() { // Here's some background discussion about overriding ClientRequest: // - https://github.com/nodejitsu/mock-request/issues/4 @@ -333,6 +334,8 @@ function restoreOverriddenClientRequest() { if (!originalClientRequest) { debug('- ClientRequest was not overridden') } else { + isNockActive = false + interceptor.dispose() http.ClientRequest = originalClientRequest originalClientRequest = undefined @@ -341,9 +344,7 @@ function restoreOverriddenClientRequest() { } function isActive() { - // If ClientRequest has been overwritten by Nock then originalClientRequest is not undefined. - // This means that Nock has been activated. - return originalClientRequest !== undefined + return isNockActive } function interceptorScopes() { @@ -367,75 +368,61 @@ function activeMocks() { } function activate() { - if (originalClientRequest) { + if (isNockActive) { throw new Error('Nock already active') } - // ----- Overriding http.request and https.request: - - common.overrideRequests(function (proto, overriddenRequest, args) { - // NOTE: overriddenRequest is already bound to its module. - - const { options, callback } = common.normalizeClientRequestArgs(...args) - - if (Object.keys(options).length === 0) { - // As weird as it is, it's possible to call `http.request` without - // options, and it makes a request to localhost or somesuch. We should - // support it too, for parity. However it doesn't work today, and fixing - // it seems low priority. Giving an explicit error is nicer than - // crashing with a weird stack trace. `new ClientRequest()`, nock's - // other client-facing entry point, makes a similar check. - // https://github.com/nock/nock/pull/1386 - // https://github.com/nock/nock/pull/1440 - throw Error( - 'Making a request with empty `options` is not supported in Nock', - ) - } - - // The option per the docs is `protocol`. Its unclear if this line is meant to override that and is misspelled or if - // the intend is to explicitly keep track of which module was called using a separate name. - // Either way, `proto` is used as the source of truth from here on out. - options.proto = proto - - const interceptors = interceptorsFor(options) - - if (isOn() && interceptors) { - const matches = interceptors.some(interceptor => - interceptor.matchOrigin(options), - ) - const allowUnmocked = interceptors.some( - interceptor => interceptor.options.allowUnmocked, - ) + overrideClientRequest() + interceptor.apply() + // Force msw to forward Nock's error instead of coerce it into 500 error + interceptor.on('unhandledException', ({ controller, error }) => { + controller.errorWith(error) + }) + interceptor.on( + 'request', + async function ({ request: mswRequest, controller }) { + const request = mswRequest.clone() + const { options } = common.normalizeClientRequestArgs(request.url) + options.proto = options.protocol.slice(0, -1) + options.method = request.method + const interceptors = interceptorsFor(options) + if (isOn() && interceptors) { + const matches = interceptors.some(interceptor => + interceptor.matchOrigin(options), + ) + const allowUnmocked = interceptors.some( + interceptor => interceptor.options.allowUnmocked, + ) - if (!matches && allowUnmocked) { - let req - if (proto === 'https') { - const { ClientRequest } = http - http.ClientRequest = originalClientRequest - req = overriddenRequest(options, callback) - http.ClientRequest = ClientRequest + const nockRequest = common.convertFetchRequestToClientRequest(request) + if (!matches && allowUnmocked) { + globalEmitter.emit('no match', nockRequest) } else { - req = overriddenRequest(options, callback) + nockRequest.on('response', nockResponse => { + const response = createResponse(nockResponse, mswRequest.signal) + controller.respondWith(response) + }) + + const promise = Promise.race([ + // TODO: temp hacky way to handle allowUnmocked in startPlayback + once(nockRequest, 'real-request'), + once(nockRequest, 'error'), + once(nockRequest, 'response'), + ]) + const buffer = await request.arrayBuffer() + nockRequest.write(buffer) + nockRequest.end() + await promise } - globalEmitter.emit('no match', req) - return req - } - - // NOTE: Since we already overrode the http.ClientRequest we are in fact constructing - // our own OverriddenClientRequest. - return new http.ClientRequest(options, callback) - } else { - globalEmitter.emit('no match', options) - if (isOff() || isEnabledForNetConnect(options)) { - return overriddenRequest(options, callback) } else { - const error = new NetConnectNotAllowedError(options.host, options.path) - return new ErroringClientRequest(error) + globalEmitter.emit('no match', options) + if (!(isOff() || isEnabledForNetConnect(options))) { + throw new NetConnectNotAllowedError(options.host, options.path) + } } - } - }) - - overrideClientRequest() + }, + ) + isNockActive = true } module.exports = { diff --git a/node_modules/nock/lib/intercepted_request_router.js b/node_modules/nock/lib/intercepted_request_router.js index d82c2446b5..76a7c312c1 100644 --- a/node_modules/nock/lib/intercepted_request_router.js +++ b/node_modules/nock/lib/intercepted_request_router.js @@ -1,12 +1,7 @@ 'use strict' -const debug = require('debug')('nock.request_overrider') -const { - IncomingMessage, - ClientRequest, - request: originalHttpRequest, -} = require('http') -const { request: originalHttpsRequest } = require('https') +const { request_overrider: debug } = require('./debug') +const { IncomingMessage, ClientRequest } = require('http') const propagate = require('propagate') const common = require('./common') const globalEmitter = require('./global_emitter') @@ -333,14 +328,7 @@ class InterceptedRequestRouter { ) if (allowUnmocked && req instanceof ClientRequest) { - const newReq = - options.proto === 'https' - ? originalHttpsRequest(options) - : originalHttpRequest(options) - - propagate(newReq, req) - // We send the raw buffer as we received it, not as we interpreted it. - newReq.end(requestBodyBuffer) + req.emit('real-request') } else { const reqStr = common.stringifyRequest(options, requestBodyString) const err = new Error(`Nock: No match for request ${reqStr}`) diff --git a/node_modules/nock/lib/interceptor.js b/node_modules/nock/lib/interceptor.js index 00c4522f6f..1ffe05b648 100644 --- a/node_modules/nock/lib/interceptor.js +++ b/node_modules/nock/lib/interceptor.js @@ -248,14 +248,7 @@ module.exports = class Interceptor { } match(req, options, body) { - // check if the logger is enabled because the stringifies can be expensive. - if (this.scope.logger.enabled) { - this.scope.logger( - 'attempting match %s, body = %s', - stringify(options), - stringify(body), - ) - } + this.scope.logger('attempting match %j, body = %j', options, body) const method = (options.method || 'GET').toUpperCase() let { path = '/' } = options diff --git a/node_modules/nock/lib/match_body.js b/node_modules/nock/lib/match_body.js index 436b7b53a0..3d568ecbd7 100644 --- a/node_modules/nock/lib/match_body.js +++ b/node_modules/nock/lib/match_body.js @@ -63,10 +63,11 @@ module.exports = function matchBody(options, spec, body) { function mapValues(object, cb) { const keys = Object.keys(object) + const clonedObject = { ...object } for (const key of keys) { - object[key] = cb(object[key], key, object) + clonedObject[key] = cb(clonedObject[key], key, clonedObject) } - return object + return clonedObject } /** diff --git a/node_modules/nock/lib/playback_interceptor.js b/node_modules/nock/lib/playback_interceptor.js index a0bae8e8a3..0d3bd6f40f 100644 --- a/node_modules/nock/lib/playback_interceptor.js +++ b/node_modules/nock/lib/playback_interceptor.js @@ -3,7 +3,7 @@ const stream = require('stream') const util = require('util') const zlib = require('zlib') -const debug = require('debug')('nock.playback_interceptor') +const { playback_interceptor: debug } = require('./debug') const common = require('./common') function parseJSONRequestBody(req, requestBody) { diff --git a/node_modules/nock/lib/recorder.js b/node_modules/nock/lib/recorder.js index 91b3e3ff36..4d70ac3bbd 100644 --- a/node_modules/nock/lib/recorder.js +++ b/node_modules/nock/lib/recorder.js @@ -1,16 +1,24 @@ 'use strict' -const debug = require('debug')('nock.recorder') +const { recorder: debug } = require('./debug') const querystring = require('querystring') const { inspect } = require('util') const common = require('./common') const { restoreOverriddenClientRequest } = require('./intercept') - +const { EventEmitter } = require('stream') +const { gzipSync, brotliCompressSync, deflateSync } = require('zlib') +const { + default: nodeInterceptors, +} = require('@mswjs/interceptors/presets/node') const SEPARATOR = '\n<<<<<<-- cut here -->>>>>>\n' let recordingInProgress = false let outputs = [] +// TODO: don't reuse the nodeInterceptors, create new ones. +const clientRequestInterceptor = nodeInterceptors[0] +const fetchRequestInterceptor = nodeInterceptors[2] + function getScope(options) { const { proto, host, port } = common.normalizeRequestOptions(options) return common.normalizeOrigin(proto, host, port) @@ -210,28 +218,67 @@ function record(recOptions) { // we restore any requests that may have been overridden by other parts of nock (e.g. intercept) // NOTE: This is hacky as hell but it keeps the backward compatibility *and* allows correct // behavior in the face of other modules also overriding ClientRequest. - common.restoreOverriddenRequests() + // common.restoreOverriddenRequests() // We restore ClientRequest as it messes with recording of modules that also override ClientRequest (e.g. xhr2) restoreOverriddenClientRequest() // We override the requests so that we can save information on them before executing. - common.overrideRequests(function (proto, overriddenRequest, rawArgs) { - const { options, callback } = common.normalizeClientRequestArgs(...rawArgs) - const bodyChunks = [] + clientRequestInterceptor.apply() + fetchRequestInterceptor.apply() + clientRequestInterceptor.on('request', async function ({ request }) { + await recordRequest(request) + }) + fetchRequestInterceptor.on('request', async function ({ request }) { + await recordRequest(request) + }) + + async function recordRequest(mswRequest) { + const request = mswRequest.clone() + const { options } = common.normalizeClientRequestArgs(request.url) + options.method = request.method + const proto = options.protocol.slice(0, -1) // Node 0.11 https.request calls http.request -- don't want to record things // twice. /* istanbul ignore if */ if (options._recording) { - return overriddenRequest(options, callback) + return } options._recording = true - const req = overriddenRequest(options, function (res) { + const req = new EventEmitter() + req.on('response', function () { debug(thisRecordingId, 'intercepting', proto, 'request to record') - // We put our 'end' listener to the front of the listener array. - res.once('end', function () { + clientRequestInterceptor.once('response', async function ({ response }) { + await recordResponse(response) + }) + fetchRequestInterceptor.once('response', async function ({ response }) { + // fetch decompresses the body automatically, so we need to recompress it + const codings = + response.headers + .get('content-encoding') + ?.toLowerCase() + .split(',') + .map(c => c.trim()) || [] + + let body = await response.arrayBuffer() + for (const coding of codings) { + if (coding === 'gzip') { + body = gzipSync(body) + } else if (coding === 'deflate') { + body = deflateSync(body) + } else if (coding === 'br') { + body = brotliCompressSync(body) + } + } + + await recordResponse(new Response(body, response)) + }) + + // Intercept "res.once('end', ...)"-like event + async function recordResponse(mswResponse) { + const response = mswResponse.clone() debug(thisRecordingId, proto, 'intercepted request ended') let reqheaders @@ -239,19 +286,26 @@ function record(recOptions) { if (enableReqHeadersRecording) { // We never record user-agent headers as they are worse than useless - // they actually make testing more difficult without providing any benefit (see README) - reqheaders = req.getHeaders() + reqheaders = Object.fromEntries(request.headers.entries()) common.deleteHeadersField(reqheaders, 'user-agent') } + const headers = Object.fromEntries(response.headers.entries()) + const res = { + statusCode: response.status, + headers, + rawHeaders: headers, + } + const generateFn = outputObjects ? generateRequestAndResponseObject : generateRequestAndResponse let out = generateFn({ - req, - bodyChunks, + req: options, + bodyChunks: [Buffer.from(await request.arrayBuffer())], options, res, - dataChunks, + dataChunks: [Buffer.from(await response.arrayBuffer())], reqheaders, }) @@ -282,33 +336,6 @@ function record(recOptions) { logging(out) } } - }) - - let encoding - // We need to be aware of changes to the stream's encoding so that we - // don't accidentally mangle the data. - const { setEncoding } = res - res.setEncoding = function (newEncoding) { - encoding = newEncoding - return setEncoding.apply(this, arguments) - } - - const dataChunks = [] - // Replace res.push with our own implementation that stores chunks - const origResPush = res.push - res.push = function (data) { - if (data) { - if (encoding) { - data = Buffer.from(data, encoding) - } - dataChunks.push(data) - } - - return origResPush.call(res, data) - } - - if (callback) { - callback(res, options, callback) } debug('finished setting up intercepting') @@ -322,46 +349,11 @@ function record(recOptions) { } }) - const recordChunk = (chunk, encoding) => { - debug(thisRecordingId, 'new', proto, 'body chunk') - if (!Buffer.isBuffer(chunk)) { - chunk = Buffer.from(chunk, encoding) - } - bodyChunks.push(chunk) - } - - const oldWrite = req.write - req.write = function (chunk, encoding) { - if (typeof chunk !== 'undefined') { - recordChunk(chunk, encoding) - oldWrite.apply(req, arguments) - } else { - throw new Error('Data was undefined.') - } - } - - // Starting in Node 8, `OutgoingMessage.end()` directly calls an internal - // `write_` function instead of proxying to the public - // `OutgoingMessage.write()` method, so we have to wrap `end` too. - const oldEnd = req.end - req.end = function (chunk, encoding, callback) { - debug('req.end') - if (typeof chunk === 'function') { - callback = chunk - chunk = null - } else if (typeof encoding === 'function') { - callback = encoding - encoding = null - } - - if (chunk) { - recordChunk(chunk, encoding) - } - oldEnd.call(req, chunk, encoding, callback) - } - - return req - }) + // This is a massive change, we are trying to change minimum code, so we emit end event here + // because mswjs take care for these events + // TODO: refactor the recorder, we no longer need all the listeners and can just record the request we get from MSW + req.emit('response') + } } // Restore *all* the overridden http/https modules' properties. @@ -371,7 +363,8 @@ function restore() { 'restoring all the overridden http/https properties', ) - common.restoreOverriddenRequests() + clientRequestInterceptor.dispose() + fetchRequestInterceptor.dispose() restoreOverriddenClientRequest() recordingInProgress = false } diff --git a/node_modules/nock/lib/scope.js b/node_modules/nock/lib/scope.js index eb51e80d63..2d29a56d1d 100644 --- a/node_modules/nock/lib/scope.js +++ b/node_modules/nock/lib/scope.js @@ -3,11 +3,11 @@ /** * @module nock/scope */ +const { scopeDebuglog } = require('./debug') const { addInterceptor, isOn } = require('./intercept') const common = require('./common') const assert = require('assert') const url = require('url') -const debug = require('debug')('nock.scope') const { EventEmitter } = require('events') const Interceptor = require('./interceptor') @@ -99,7 +99,7 @@ class Scope extends EventEmitter { logNamespace = this.urlParts.host } - this.logger = debug.extend(logNamespace) + this.logger = scopeDebuglog(logNamespace) } add(key, interceptor) { diff --git a/node_modules/nock/lib/socket.js b/node_modules/nock/lib/socket.js index 4651aa79f9..69fc6cc510 100644 --- a/node_modules/nock/lib/socket.js +++ b/node_modules/nock/lib/socket.js @@ -1,7 +1,7 @@ 'use strict' const { EventEmitter } = require('events') -const debug = require('debug')('nock.socket') +const { socket: debug } = require('./debug') module.exports = class Socket extends EventEmitter { constructor(options) { diff --git a/node_modules/nock/package.json b/node_modules/nock/package.json index 02c28b9bb5..3f1bfdf0ca 100644 --- a/node_modules/nock/package.json +++ b/node_modules/nock/package.json @@ -7,7 +7,7 @@ "testing", "isolation" ], - "version": "13.5.6", + "version": "14.0.0", "author": "Pedro Teixeira ", "repository": { "type": "git", @@ -17,12 +17,12 @@ "url": "https://github.com/nock/nock/issues" }, "engines": { - "node": ">= 10.13" + "node": ">= 18" }, "main": "./index.js", "types": "types", "dependencies": { - "debug": "^4.1.0", + "@mswjs/interceptors": "^0.37.3", "json-stringify-safe": "^5.0.1", "propagate": "^2.0.0" }, @@ -49,7 +49,7 @@ "proxyquire": "^2.1.0", "rimraf": "^3.0.0", "semantic-release": "^24.1.0", - "sinon": "^15.0.1", + "sinon": "^17.0.1", "sinon-chai": "^3.7.0", "typescript": "^5.0.4" }, diff --git a/node_modules/nock/types/index.d.ts b/node_modules/nock/types/index.d.ts index 9c0ec385c0..435022c587 100644 --- a/node_modules/nock/types/index.d.ts +++ b/node_modules/nock/types/index.d.ts @@ -205,8 +205,13 @@ declare namespace nock { thrice(): this optionally(flag?: boolean): this + delay(opts: number): this + /** @deprecated use delay(number) instead */ + delay(opts: { head?: number; body?: number }): this delay(opts: number | { head?: number; body?: number }): this + /** @deprecated use delay function instead */ delayBody(timeMs: number): this + /** @deprecated use delay function instead */ delayConnection(timeMs: number): this } diff --git a/node_modules/outvariant/LICENSE b/node_modules/outvariant/LICENSE new file mode 100644 index 0000000000..6df95d64e7 --- /dev/null +++ b/node_modules/outvariant/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2021–present Artem Zakharchenko + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/outvariant/README.md b/node_modules/outvariant/README.md new file mode 100644 index 0000000000..58d69edbe5 --- /dev/null +++ b/node_modules/outvariant/README.md @@ -0,0 +1,146 @@ +# `outvariant` + +Type-safe implementation of invariant with positionals. + +## Motivation + +### Type-safely + +This implementation asserts the given predicate expression so it's treated as non-nullable after the `invariant` call: + +```ts +// Regular invariant: +invariant(user, 'Failed to fetch') +user?.firstName // "user" is possibly undefined + +// Outvariant: +invariant(user, 'Failed to fetch') +user.firstName // OK, "invariant" ensured the "user" exists +``` + +### Positionals support + +This implementation uses [rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) to support dynamic number of positionals: + +```js +invariant(predicate, 'Expected %s but got %s', 'one', false) +``` + +## What is this for? + +Invariant is a shorthand function that asserts a given predicate and throws an error if that predicate is false. + +Compare these two pieces of code identical in behavior: + +```js +if (!token) { + throw new Error(`Expected a token to be set but got ${typeof token}`) +} +``` + +```js +import { invariant } from 'outvariant' + +invariant(token, 'Expected a token to be set but got %s', typeof token) +``` + +Using `invariant` reduces the visual nesting of the code and leads to cleaner error messages thanks to formatted positionals (i.e. the `%s` (string) positional above). + +## Usage + +### Install + +```sh +npm install outvariant +# or +yarn add outvariant +``` + +> You may want to install this library as a dev dependency (`-D`) based on your usage. + +### Write an assertion + +```js +import { invariant } from 'outvariant' + +invariant(user, 'Failed to load: expected user, but got %o', user) +``` + +## Positionals + +The following positional tokens are supported: + +| Token | Expected value type | +| --------- | ------------------------------------------------------- | +| `%s` | String | +| `%d`/`%i` | Number | +| `%j` | JSON (non-stringified) | +| `%o` | Arbitrary object or object-like (i.e. a class instance) | + +Whenever present in the error message, a positional token will look up the value to insert in its place from the arguments given to `invariant`. + +```js +invariant( + false, + 'Expected the "%s" property but got %j', + // Note that positionals are sensitive to order: + // - "firstName" replaces "%s" because it's first. + // - {"id":1} replaces "%j" because it's second. + 'firstName', + { + id: 1, + } +) +``` + +## Polymorphic errors + +It is possible to throw a custom `Error` instance using `invariant.as`: + +```js +import { invariant } from 'outvariant' + +class NetworkError extends Error { + constructor(message) { + super(message) + } +} + +invariant.as(NetworkError, res.fulfilled, 'Failed to handle response') +``` + +Note that providing a custom error constructor as the argument to `invariant.as` requires the custom constructor's signature to be compatible with the `Error` class constructor. + +If your error constructor has a different signature, you can pass a function as the first argument to `invariant.as` that creates a new custom error instance. + +```js +import { invariant } from 'outvariant' + +class NetworkError extends Error { + constructor(statusCode, message) { + super(message) + this.statusCode = statusCode + } +} + +invariant.as( + (message) => new NetworkError(500, message), + res.fulfilled, + 'Failed to handle response' +) +``` + +Abstract the error into helper functions for flexibility: + +```js +function toNetworkError(statusCode) { + return (message) => new NetworkError(statusCode, message) +} + +invariant.as(toNetworkError(404), res?.user?.id, 'User Not Found') +invariant.as(toNetworkError(500), res.fulfilled, 'Internal Server Error') +``` + +## Contributing + +Please [open an issue](https://github.com/open-draft/outvariant/issues) or [submit a pull request](https://github.com/open-draft/outvariant/pulls) if you wish to contribute. Thank you. diff --git a/node_modules/outvariant/lib/index.d.ts b/node_modules/outvariant/lib/index.d.ts new file mode 100644 index 0000000000..b6ecc90bbb --- /dev/null +++ b/node_modules/outvariant/lib/index.d.ts @@ -0,0 +1,21 @@ +declare class InvariantError extends Error { + readonly message: string; + name: string; + constructor(message: string, ...positionals: any[]); +} +interface CustomErrorConstructor { + new (message: string): Error; +} +interface CustomErrorFactory { + (message: string): Error; +} +declare type CustomError = CustomErrorConstructor | CustomErrorFactory; +declare type Invariant = { + (predicate: unknown, message: string, ...positionals: any[]): asserts predicate; + as(ErrorConstructor: CustomError, predicate: unknown, message: string, ...positionals: unknown[]): asserts predicate; +}; +declare const invariant: Invariant; + +declare function format(message: string, ...positionals: any[]): string; + +export { CustomError, CustomErrorConstructor, CustomErrorFactory, InvariantError, format, invariant }; diff --git a/node_modules/outvariant/lib/index.js b/node_modules/outvariant/lib/index.js new file mode 100644 index 0000000000..19c973d230 --- /dev/null +++ b/node_modules/outvariant/lib/index.js @@ -0,0 +1,120 @@ +"use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + InvariantError: () => InvariantError, + format: () => format, + invariant: () => invariant +}); +module.exports = __toCommonJS(src_exports); + +// src/format.ts +var POSITIONALS_EXP = /(%?)(%([sdijo]))/g; +function serializePositional(positional, flag) { + switch (flag) { + case "s": + return positional; + case "d": + case "i": + return Number(positional); + case "j": + return JSON.stringify(positional); + case "o": { + if (typeof positional === "string") { + return positional; + } + const json = JSON.stringify(positional); + if (json === "{}" || json === "[]" || /^\[object .+?\]$/.test(json)) { + return positional; + } + return json; + } + } +} +function format(message, ...positionals) { + if (positionals.length === 0) { + return message; + } + let positionalIndex = 0; + let formattedMessage = message.replace( + POSITIONALS_EXP, + (match, isEscaped, _, flag) => { + const positional = positionals[positionalIndex]; + const value = serializePositional(positional, flag); + if (!isEscaped) { + positionalIndex++; + return value; + } + return match; + } + ); + if (positionalIndex < positionals.length) { + formattedMessage += ` ${positionals.slice(positionalIndex).join(" ")}`; + } + formattedMessage = formattedMessage.replace(/%{2,2}/g, "%"); + return formattedMessage; +} + +// src/invariant.ts +var STACK_FRAMES_TO_IGNORE = 2; +function cleanErrorStack(error) { + if (!error.stack) { + return; + } + const nextStack = error.stack.split("\n"); + nextStack.splice(1, STACK_FRAMES_TO_IGNORE); + error.stack = nextStack.join("\n"); +} +var InvariantError = class extends Error { + constructor(message, ...positionals) { + super(message); + this.message = message; + this.name = "Invariant Violation"; + this.message = format(message, ...positionals); + cleanErrorStack(this); + } +}; +var invariant = (predicate, message, ...positionals) => { + if (!predicate) { + throw new InvariantError(message, ...positionals); + } +}; +invariant.as = (ErrorConstructor, predicate, message, ...positionals) => { + if (!predicate) { + const formatMessage = positionals.length === 0 ? message : format(message, ...positionals); + let error; + try { + error = Reflect.construct(ErrorConstructor, [ + formatMessage + ]); + } catch (err) { + error = ErrorConstructor(formatMessage); + } + throw error; + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + InvariantError, + format, + invariant +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/outvariant/lib/index.js.map b/node_modules/outvariant/lib/index.js.map new file mode 100644 index 0000000000..ba5bf07175 --- /dev/null +++ b/node_modules/outvariant/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/index.ts","../src/format.ts","../src/invariant.ts"],"sourcesContent":["export * from './invariant'\nexport * from './format'\n","const POSITIONALS_EXP = /(%?)(%([sdijo]))/g\n\nfunction serializePositional(positional: any, flag: string): any {\n switch (flag) {\n // Strings.\n case 's':\n return positional\n\n // Digits.\n case 'd':\n case 'i':\n return Number(positional)\n\n // JSON.\n case 'j':\n return JSON.stringify(positional)\n\n // Objects.\n case 'o': {\n // Preserve stings to prevent extra quotes around them.\n if (typeof positional === 'string') {\n return positional\n }\n\n const json = JSON.stringify(positional)\n\n // If the positional isn't serializable, return it as-is.\n if (json === '{}' || json === '[]' || /^\\[object .+?\\]$/.test(json)) {\n return positional\n }\n\n return json\n }\n }\n}\n\nexport function format(message: string, ...positionals: any[]): string {\n if (positionals.length === 0) {\n return message\n }\n\n let positionalIndex = 0\n let formattedMessage = message.replace(\n POSITIONALS_EXP,\n (match, isEscaped, _, flag) => {\n const positional = positionals[positionalIndex]\n const value = serializePositional(positional, flag)\n\n if (!isEscaped) {\n positionalIndex++\n return value\n }\n\n return match\n }\n )\n\n // Append unresolved positionals to string as-is.\n if (positionalIndex < positionals.length) {\n formattedMessage += ` ${positionals.slice(positionalIndex).join(' ')}`\n }\n\n formattedMessage = formattedMessage.replace(/%{2,2}/g, '%')\n\n return formattedMessage\n}\n","import { format } from './format'\n\nconst STACK_FRAMES_TO_IGNORE = 2\n\n/**\n * Remove the \"outvariant\" package trace from the given error.\n * This scopes down the error stack to the relevant parts\n * when used in other applications.\n */\nfunction cleanErrorStack(error: Error): void {\n if (!error.stack) {\n return\n }\n\n const nextStack = error.stack.split('\\n')\n nextStack.splice(1, STACK_FRAMES_TO_IGNORE)\n error.stack = nextStack.join('\\n')\n}\n\nexport class InvariantError extends Error {\n name = 'Invariant Violation'\n\n constructor(public readonly message: string, ...positionals: any[]) {\n super(message)\n this.message = format(message, ...positionals)\n cleanErrorStack(this)\n }\n}\n\nexport interface CustomErrorConstructor {\n new (message: string): Error\n}\n\nexport interface CustomErrorFactory {\n (message: string): Error\n}\n\nexport type CustomError = CustomErrorConstructor | CustomErrorFactory\n\ntype Invariant = {\n (\n predicate: unknown,\n message: string,\n ...positionals: any[]\n ): asserts predicate\n\n as(\n ErrorConstructor: CustomError,\n predicate: unknown,\n message: string,\n ...positionals: unknown[]\n ): asserts predicate\n}\n\nexport const invariant: Invariant = (\n predicate,\n message,\n ...positionals\n): asserts predicate => {\n if (!predicate) {\n throw new InvariantError(message, ...positionals)\n }\n}\n\ninvariant.as = (ErrorConstructor, predicate, message, ...positionals) => {\n if (!predicate) {\n const formatMessage =\n positionals.length === 0 ? message : format(message, ...positionals)\n let error: Error\n\n try {\n error = Reflect.construct(ErrorConstructor as CustomErrorConstructor, [\n formatMessage,\n ])\n } catch (err) {\n error = (ErrorConstructor as CustomErrorFactory)(formatMessage)\n }\n\n throw error\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAM,kBAAkB;AAExB,SAAS,oBAAoB,YAAiB,MAAmB;AAC/D,UAAQ,MAAM;AAAA,IAEZ,KAAK;AACH,aAAO;AAAA,IAGT,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO,UAAU;AAAA,IAG1B,KAAK;AACH,aAAO,KAAK,UAAU,UAAU;AAAA,IAGlC,KAAK,KAAK;AAER,UAAI,OAAO,eAAe,UAAU;AAClC,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,KAAK,UAAU,UAAU;AAGtC,UAAI,SAAS,QAAQ,SAAS,QAAQ,mBAAmB,KAAK,IAAI,GAAG;AACnE,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,OAAO,YAAoB,aAA4B;AACrE,MAAI,YAAY,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,MAAI,kBAAkB;AACtB,MAAI,mBAAmB,QAAQ;AAAA,IAC7B;AAAA,IACA,CAAC,OAAO,WAAW,GAAG,SAAS;AAC7B,YAAM,aAAa,YAAY;AAC/B,YAAM,QAAQ,oBAAoB,YAAY,IAAI;AAElD,UAAI,CAAC,WAAW;AACd;AACA,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,kBAAkB,YAAY,QAAQ;AACxC,wBAAoB,IAAI,YAAY,MAAM,eAAe,EAAE,KAAK,GAAG;AAAA,EACrE;AAEA,qBAAmB,iBAAiB,QAAQ,WAAW,GAAG;AAE1D,SAAO;AACT;;;AC/DA,IAAM,yBAAyB;AAO/B,SAAS,gBAAgB,OAAoB;AAC3C,MAAI,CAAC,MAAM,OAAO;AAChB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,MAAM,MAAM,IAAI;AACxC,YAAU,OAAO,GAAG,sBAAsB;AAC1C,QAAM,QAAQ,UAAU,KAAK,IAAI;AACnC;AAEO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAGxC,YAA4B,YAAoB,aAAoB;AAClE,UAAM,OAAO;AADa;AAF5B,gBAAO;AAIL,SAAK,UAAU,OAAO,SAAS,GAAG,WAAW;AAC7C,oBAAgB,IAAI;AAAA,EACtB;AACF;AA2BO,IAAM,YAAuB,CAClC,WACA,YACG,gBACmB;AACtB,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,eAAe,SAAS,GAAG,WAAW;AAAA,EAClD;AACF;AAEA,UAAU,KAAK,CAAC,kBAAkB,WAAW,YAAY,gBAAgB;AACvE,MAAI,CAAC,WAAW;AACd,UAAM,gBACJ,YAAY,WAAW,IAAI,UAAU,OAAO,SAAS,GAAG,WAAW;AACrE,QAAI;AAEJ,QAAI;AACF,cAAQ,QAAQ,UAAU,kBAA4C;AAAA,QACpE;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAP;AACA,cAAS,iBAAwC,aAAa;AAAA,IAChE;AAEA,UAAM;AAAA,EACR;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/outvariant/lib/index.mjs b/node_modules/outvariant/lib/index.mjs new file mode 100644 index 0000000000..6e81f9953d --- /dev/null +++ b/node_modules/outvariant/lib/index.mjs @@ -0,0 +1,91 @@ +// src/format.ts +var POSITIONALS_EXP = /(%?)(%([sdijo]))/g; +function serializePositional(positional, flag) { + switch (flag) { + case "s": + return positional; + case "d": + case "i": + return Number(positional); + case "j": + return JSON.stringify(positional); + case "o": { + if (typeof positional === "string") { + return positional; + } + const json = JSON.stringify(positional); + if (json === "{}" || json === "[]" || /^\[object .+?\]$/.test(json)) { + return positional; + } + return json; + } + } +} +function format(message, ...positionals) { + if (positionals.length === 0) { + return message; + } + let positionalIndex = 0; + let formattedMessage = message.replace( + POSITIONALS_EXP, + (match, isEscaped, _, flag) => { + const positional = positionals[positionalIndex]; + const value = serializePositional(positional, flag); + if (!isEscaped) { + positionalIndex++; + return value; + } + return match; + } + ); + if (positionalIndex < positionals.length) { + formattedMessage += ` ${positionals.slice(positionalIndex).join(" ")}`; + } + formattedMessage = formattedMessage.replace(/%{2,2}/g, "%"); + return formattedMessage; +} + +// src/invariant.ts +var STACK_FRAMES_TO_IGNORE = 2; +function cleanErrorStack(error) { + if (!error.stack) { + return; + } + const nextStack = error.stack.split("\n"); + nextStack.splice(1, STACK_FRAMES_TO_IGNORE); + error.stack = nextStack.join("\n"); +} +var InvariantError = class extends Error { + constructor(message, ...positionals) { + super(message); + this.message = message; + this.name = "Invariant Violation"; + this.message = format(message, ...positionals); + cleanErrorStack(this); + } +}; +var invariant = (predicate, message, ...positionals) => { + if (!predicate) { + throw new InvariantError(message, ...positionals); + } +}; +invariant.as = (ErrorConstructor, predicate, message, ...positionals) => { + if (!predicate) { + const formatMessage = positionals.length === 0 ? message : format(message, ...positionals); + let error; + try { + error = Reflect.construct(ErrorConstructor, [ + formatMessage + ]); + } catch (err) { + error = ErrorConstructor(formatMessage); + } + throw error; + } +}; +export { + InvariantError, + format, + invariant +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/outvariant/lib/index.mjs.map b/node_modules/outvariant/lib/index.mjs.map new file mode 100644 index 0000000000..b08695db36 --- /dev/null +++ b/node_modules/outvariant/lib/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/format.ts","../src/invariant.ts"],"sourcesContent":["const POSITIONALS_EXP = /(%?)(%([sdijo]))/g\n\nfunction serializePositional(positional: any, flag: string): any {\n switch (flag) {\n // Strings.\n case 's':\n return positional\n\n // Digits.\n case 'd':\n case 'i':\n return Number(positional)\n\n // JSON.\n case 'j':\n return JSON.stringify(positional)\n\n // Objects.\n case 'o': {\n // Preserve stings to prevent extra quotes around them.\n if (typeof positional === 'string') {\n return positional\n }\n\n const json = JSON.stringify(positional)\n\n // If the positional isn't serializable, return it as-is.\n if (json === '{}' || json === '[]' || /^\\[object .+?\\]$/.test(json)) {\n return positional\n }\n\n return json\n }\n }\n}\n\nexport function format(message: string, ...positionals: any[]): string {\n if (positionals.length === 0) {\n return message\n }\n\n let positionalIndex = 0\n let formattedMessage = message.replace(\n POSITIONALS_EXP,\n (match, isEscaped, _, flag) => {\n const positional = positionals[positionalIndex]\n const value = serializePositional(positional, flag)\n\n if (!isEscaped) {\n positionalIndex++\n return value\n }\n\n return match\n }\n )\n\n // Append unresolved positionals to string as-is.\n if (positionalIndex < positionals.length) {\n formattedMessage += ` ${positionals.slice(positionalIndex).join(' ')}`\n }\n\n formattedMessage = formattedMessage.replace(/%{2,2}/g, '%')\n\n return formattedMessage\n}\n","import { format } from './format'\n\nconst STACK_FRAMES_TO_IGNORE = 2\n\n/**\n * Remove the \"outvariant\" package trace from the given error.\n * This scopes down the error stack to the relevant parts\n * when used in other applications.\n */\nfunction cleanErrorStack(error: Error): void {\n if (!error.stack) {\n return\n }\n\n const nextStack = error.stack.split('\\n')\n nextStack.splice(1, STACK_FRAMES_TO_IGNORE)\n error.stack = nextStack.join('\\n')\n}\n\nexport class InvariantError extends Error {\n name = 'Invariant Violation'\n\n constructor(public readonly message: string, ...positionals: any[]) {\n super(message)\n this.message = format(message, ...positionals)\n cleanErrorStack(this)\n }\n}\n\nexport interface CustomErrorConstructor {\n new (message: string): Error\n}\n\nexport interface CustomErrorFactory {\n (message: string): Error\n}\n\nexport type CustomError = CustomErrorConstructor | CustomErrorFactory\n\ntype Invariant = {\n (\n predicate: unknown,\n message: string,\n ...positionals: any[]\n ): asserts predicate\n\n as(\n ErrorConstructor: CustomError,\n predicate: unknown,\n message: string,\n ...positionals: unknown[]\n ): asserts predicate\n}\n\nexport const invariant: Invariant = (\n predicate,\n message,\n ...positionals\n): asserts predicate => {\n if (!predicate) {\n throw new InvariantError(message, ...positionals)\n }\n}\n\ninvariant.as = (ErrorConstructor, predicate, message, ...positionals) => {\n if (!predicate) {\n const formatMessage =\n positionals.length === 0 ? message : format(message, ...positionals)\n let error: Error\n\n try {\n error = Reflect.construct(ErrorConstructor as CustomErrorConstructor, [\n formatMessage,\n ])\n } catch (err) {\n error = (ErrorConstructor as CustomErrorFactory)(formatMessage)\n }\n\n throw error\n }\n}\n"],"mappings":";AAAA,IAAM,kBAAkB;AAExB,SAAS,oBAAoB,YAAiB,MAAmB;AAC/D,UAAQ,MAAM;AAAA,IAEZ,KAAK;AACH,aAAO;AAAA,IAGT,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO,UAAU;AAAA,IAG1B,KAAK;AACH,aAAO,KAAK,UAAU,UAAU;AAAA,IAGlC,KAAK,KAAK;AAER,UAAI,OAAO,eAAe,UAAU;AAClC,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,KAAK,UAAU,UAAU;AAGtC,UAAI,SAAS,QAAQ,SAAS,QAAQ,mBAAmB,KAAK,IAAI,GAAG;AACnE,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,OAAO,YAAoB,aAA4B;AACrE,MAAI,YAAY,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,MAAI,kBAAkB;AACtB,MAAI,mBAAmB,QAAQ;AAAA,IAC7B;AAAA,IACA,CAAC,OAAO,WAAW,GAAG,SAAS;AAC7B,YAAM,aAAa,YAAY;AAC/B,YAAM,QAAQ,oBAAoB,YAAY,IAAI;AAElD,UAAI,CAAC,WAAW;AACd;AACA,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,kBAAkB,YAAY,QAAQ;AACxC,wBAAoB,IAAI,YAAY,MAAM,eAAe,EAAE,KAAK,GAAG;AAAA,EACrE;AAEA,qBAAmB,iBAAiB,QAAQ,WAAW,GAAG;AAE1D,SAAO;AACT;;;AC/DA,IAAM,yBAAyB;AAO/B,SAAS,gBAAgB,OAAoB;AAC3C,MAAI,CAAC,MAAM,OAAO;AAChB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,MAAM,MAAM,IAAI;AACxC,YAAU,OAAO,GAAG,sBAAsB;AAC1C,QAAM,QAAQ,UAAU,KAAK,IAAI;AACnC;AAEO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAGxC,YAA4B,YAAoB,aAAoB;AAClE,UAAM,OAAO;AADa;AAF5B,gBAAO;AAIL,SAAK,UAAU,OAAO,SAAS,GAAG,WAAW;AAC7C,oBAAgB,IAAI;AAAA,EACtB;AACF;AA2BO,IAAM,YAAuB,CAClC,WACA,YACG,gBACmB;AACtB,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,eAAe,SAAS,GAAG,WAAW;AAAA,EAClD;AACF;AAEA,UAAU,KAAK,CAAC,kBAAkB,WAAW,YAAY,gBAAgB;AACvE,MAAI,CAAC,WAAW;AACd,UAAM,gBACJ,YAAY,WAAW,IAAI,UAAU,OAAO,SAAS,GAAG,WAAW;AACrE,QAAI;AAEJ,QAAI;AACF,cAAQ,QAAQ,UAAU,kBAA4C;AAAA,QACpE;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAP;AACA,cAAS,iBAAwC,aAAa;AAAA,IAChE;AAEA,UAAM;AAAA,EACR;AACF;","names":[]} \ No newline at end of file diff --git a/node_modules/outvariant/package.json b/node_modules/outvariant/package.json new file mode 100644 index 0000000000..31bc82cd69 --- /dev/null +++ b/node_modules/outvariant/package.json @@ -0,0 +1,47 @@ +{ + "name": "outvariant", + "version": "1.4.3", + "description": "Type-safe implementation of invariant with positionals.", + "main": "lib/index.js", + "module": "lib/index.mjs", + "typings": "lib/index.d.ts", + "exports": { + ".": { + "types": "./lib/index.d.ts", + "require": "./lib/index.js", + "default": "./lib/index.mjs" + } + }, + "author": "Artem Zakharchenko", + "license": "MIT", + "scripts": { + "test": "jest", + "clean": "rimraf ./lib", + "build": "yarn clean && tsup", + "prepublishOnly": "yarn test && yarn build", + "release": "release publish" + }, + "files": [ + "lib" + ], + "keywords": [ + "invariant", + "outvariant", + "exception", + "positional" + ], + "devDependencies": { + "@ossjs/release": "^0.8.0", + "@types/jest": "^26.0.23", + "jest": "^27.0.6", + "rimraf": "^3.0.2", + "ts-jest": "^27.0.3", + "ts-node": "^10.0.0", + "tsup": "^6.2.3", + "typescript": "^4.3.4" + }, + "repository": { + "type": "git", + "url": "https://github.com/open-draft/outvariant" + } +} \ No newline at end of file diff --git a/node_modules/strict-event-emitter/README.md b/node_modules/strict-event-emitter/README.md new file mode 100644 index 0000000000..c972baacd4 --- /dev/null +++ b/node_modules/strict-event-emitter/README.md @@ -0,0 +1,79 @@ +# Strict Event Emitter + +A type-safe implementation of `EventEmitter` for browser and Node.js. + +## Motivation + +Despite event emitters potentially accepting any runtime value, defining a strict event contract is crucial when developing complex event-driven architectures. Unfortunately, the native type definitions for Node's `EventEmitter` annotate event names as `string`, which forbids any stricter type validation. + +```js +// index.js +const emitter = new EventEmitter() + +// Let's say our application expects a "ping" +// event with the number payload. +emitter.on('ping', (n: number) => {}) + +// We can, however, emit a different event by mistake. +emitter.emit('pong', 1) + +// Or even the correct event with the wrong data. +emitter.emit('ping', 'wait, not a number') +``` + +The purpose of this library is to provide an `EventEmitter` instance that can accept a generic describing the expected events contract. + +```ts +import { Emitter } from 'strict-event-emitter' + +// Define a strict events contract where keys +// represent event names and values represent +// the list of arguments expected in ".emit()". +type Events = { + ping: [number] +} + +const emitter = new Emitter() +emitter.addListener('ping', (n) => { + // "n" argument type is inferred as "number'. +}) + +emitter.emit('ping', 10) // OK +emitter.emit('unknown', 10) // TypeError (invalid event name) +emitter.emit('ping', 'wait, not a number') // TypeError (invalid data) +``` + +This library is also a custom `EventEmitter` implementation, which makes it compatible with other environments, like browsers or React Native. + +## Getting started + +### Install + +```bash +npm install strict-event-emitter +``` + +### Use + +```ts +import { Emitter } from 'strict-event-emitter' + +// 1. Define an interface that describes your events. +// Set event names as the keys, and their expected payloads as values. +interface Events { + connect: [id: string] + disconnect: [id: string] +} + +// 2. Create a strict emitter and pass the previously defined "Events" +// as its first generic argument. +const emitter = new Emitter() + +// 3. Use the "emitter" the same way you'd use the regular "EventEmitter" instance. +emitter.addListener('connect', (id) => {}) +emitter.emit('connect', 'abc-123') +``` + +## License + +MIT diff --git a/node_modules/strict-event-emitter/lib/index.d.ts b/node_modules/strict-event-emitter/lib/index.d.ts new file mode 100644 index 0000000000..7068ce7ba1 --- /dev/null +++ b/node_modules/strict-event-emitter/lib/index.d.ts @@ -0,0 +1,81 @@ +declare type EventMap = { + [eventName: string]: Array; +}; +declare type InternalEventNames = 'newListener' | 'removeListener'; +declare type InternalListener = Listener<[ + eventName: keyof Events, + listener: Listener> +]>; +declare type Listener> = (...data: Data) => void; +/** + * Node.js-compatible implementation of `EventEmitter`. + * + * @example + * const emitter = new Emitter<{ hello: [string] }>() + * emitter.on('hello', (name) => console.log(name)) + * emitter.emit('hello', 'John') + */ +declare class Emitter { + private events; + private maxListeners; + private hasWarnedAboutPotentialMemoryLeak; + static defaultMaxListeners: number; + static listenerCount(emitter: Emitter, eventName: keyof Events): number; + constructor(); + private _emitInternalEvent; + private _getListeners; + private _removeListener; + private _wrapOnceListener; + setMaxListeners(maxListeners: number): this; + /** + * Returns the current max listener value for the `Emitter` which is + * either set by `emitter.setMaxListeners(n)` or defaults to + * `Emitter.defaultMaxListeners`. + */ + getMaxListeners(): number; + /** + * Returns an array listing the events for which the emitter has registered listeners. + * The values in the array will be strings or Symbols. + */ + eventNames(): Array; + /** + * Synchronously calls each of the listeners registered for the event named `eventName`, + * in the order they were registered, passing the supplied arguments to each. + * Returns `true` if the event has listeners, `false` otherwise. + * + * @example + * const emitter = new Emitter<{ hello: [string] }>() + * emitter.emit('hello', 'John') + */ + emit(eventName: EventName, ...data: Events[EventName]): boolean; + addListener(eventName: InternalEventNames, listener: InternalListener): this; + addListener(eventName: EventName, listener: Listener): this; + on(eventName: InternalEventNames, listener: InternalListener): this; + on(eventName: EventName, listener: Listener): this; + once(eventName: InternalEventNames, listener: InternalListener): this; + once(eventName: EventName, listener: Listener): this; + prependListener(eventName: InternalEventNames, listener: InternalListener): this; + prependListener(eventName: EventName, listener: Listener): this; + prependOnceListener(eventName: InternalEventNames, listener: InternalListener): this; + prependOnceListener(eventName: EventName, listener: Listener): this; + removeListener(eventName: InternalEventNames, listener: InternalListener): this; + removeListener(eventName: EventName, listener: Listener): this; + off(eventName: InternalEventNames, listener: InternalListener): this; + off(eventName: EventName, listener: Listener): this; + removeAllListeners(eventName?: InternalEventNames): this; + removeAllListeners(eventName?: EventName): this; + listeners(eventName: InternalEventNames): Array>; + listeners(eventName: EventName): Array>; + listenerCount(eventName: InternalEventNames): number; + listenerCount(eventName: EventName): number; + rawListeners(eventName: EventName): Array>; +} + +declare class MemoryLeakError extends Error { + readonly emitter: Emitter; + readonly type: string | number | symbol; + readonly count: number; + constructor(emitter: Emitter, type: string | number | symbol, count: number); +} + +export { Emitter, EventMap, InternalEventNames, InternalListener, Listener, MemoryLeakError }; diff --git a/node_modules/strict-event-emitter/lib/index.js b/node_modules/strict-event-emitter/lib/index.js new file mode 100644 index 0000000000..1d4bc820d2 --- /dev/null +++ b/node_modules/strict-event-emitter/lib/index.js @@ -0,0 +1,198 @@ +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Emitter: () => Emitter, + MemoryLeakError: () => MemoryLeakError +}); +module.exports = __toCommonJS(src_exports); + +// src/MemoryLeakError.ts +var MemoryLeakError = class extends Error { + constructor(emitter, type, count) { + super( + `Possible EventEmitter memory leak detected. ${count} ${type.toString()} listeners added. Use emitter.setMaxListeners() to increase limit` + ); + this.emitter = emitter; + this.type = type; + this.count = count; + this.name = "MaxListenersExceededWarning"; + } +}; + +// src/Emitter.ts +var _Emitter = class { + static listenerCount(emitter, eventName) { + return emitter.listenerCount(eventName); + } + constructor() { + this.events = /* @__PURE__ */ new Map(); + this.maxListeners = _Emitter.defaultMaxListeners; + this.hasWarnedAboutPotentialMemoryLeak = false; + } + _emitInternalEvent(internalEventName, eventName, listener) { + this.emit( + internalEventName, + ...[eventName, listener] + ); + } + _getListeners(eventName) { + return Array.prototype.concat.apply([], this.events.get(eventName)) || []; + } + _removeListener(listeners, listener) { + const index = listeners.indexOf(listener); + if (index > -1) { + listeners.splice(index, 1); + } + return []; + } + _wrapOnceListener(eventName, listener) { + const onceListener = (...data) => { + this.removeListener(eventName, onceListener); + return listener.apply(this, data); + }; + Object.defineProperty(onceListener, "name", { value: listener.name }); + return onceListener; + } + setMaxListeners(maxListeners) { + this.maxListeners = maxListeners; + return this; + } + /** + * Returns the current max listener value for the `Emitter` which is + * either set by `emitter.setMaxListeners(n)` or defaults to + * `Emitter.defaultMaxListeners`. + */ + getMaxListeners() { + return this.maxListeners; + } + /** + * Returns an array listing the events for which the emitter has registered listeners. + * The values in the array will be strings or Symbols. + */ + eventNames() { + return Array.from(this.events.keys()); + } + /** + * Synchronously calls each of the listeners registered for the event named `eventName`, + * in the order they were registered, passing the supplied arguments to each. + * Returns `true` if the event has listeners, `false` otherwise. + * + * @example + * const emitter = new Emitter<{ hello: [string] }>() + * emitter.emit('hello', 'John') + */ + emit(eventName, ...data) { + const listeners = this._getListeners(eventName); + listeners.forEach((listener) => { + listener.apply(this, data); + }); + return listeners.length > 0; + } + addListener(eventName, listener) { + this._emitInternalEvent("newListener", eventName, listener); + const nextListeners = this._getListeners(eventName).concat(listener); + this.events.set(eventName, nextListeners); + if (this.maxListeners > 0 && this.listenerCount(eventName) > this.maxListeners && !this.hasWarnedAboutPotentialMemoryLeak) { + this.hasWarnedAboutPotentialMemoryLeak = true; + const memoryLeakWarning = new MemoryLeakError( + this, + eventName, + this.listenerCount(eventName) + ); + console.warn(memoryLeakWarning); + } + return this; + } + on(eventName, listener) { + return this.addListener(eventName, listener); + } + once(eventName, listener) { + return this.addListener( + eventName, + this._wrapOnceListener(eventName, listener) + ); + } + prependListener(eventName, listener) { + const listeners = this._getListeners(eventName); + if (listeners.length > 0) { + const nextListeners = [listener].concat(listeners); + this.events.set(eventName, nextListeners); + } else { + this.events.set(eventName, listeners.concat(listener)); + } + return this; + } + prependOnceListener(eventName, listener) { + return this.prependListener( + eventName, + this._wrapOnceListener(eventName, listener) + ); + } + removeListener(eventName, listener) { + const listeners = this._getListeners(eventName); + if (listeners.length > 0) { + this._removeListener(listeners, listener); + this.events.set(eventName, listeners); + this._emitInternalEvent("removeListener", eventName, listener); + } + return this; + } + /** + * Alias for `emitter.removeListener()`. + * + * @example + * emitter.off('hello', listener) + */ + off(eventName, listener) { + return this.removeListener(eventName, listener); + } + removeAllListeners(eventName) { + if (eventName) { + this.events.delete(eventName); + } else { + this.events.clear(); + } + return this; + } + /** + * Returns a copy of the array of listeners for the event named `eventName`. + */ + listeners(eventName) { + return Array.from(this._getListeners(eventName)); + } + /** + * Returns the number of listeners listening to the event named `eventName`. + */ + listenerCount(eventName) { + return this._getListeners(eventName).length; + } + rawListeners(eventName) { + return this.listeners(eventName); + } +}; +var Emitter = _Emitter; +Emitter.defaultMaxListeners = 10; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + Emitter, + MemoryLeakError +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/strict-event-emitter/lib/index.js.map b/node_modules/strict-event-emitter/lib/index.js.map new file mode 100644 index 0000000000..6dd965299d --- /dev/null +++ b/node_modules/strict-event-emitter/lib/index.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/index.ts","../src/MemoryLeakError.ts","../src/Emitter.ts"],"sourcesContent":["export * from './Emitter'\nexport * from './MemoryLeakError'\n","import type { Emitter } from './Emitter'\n\nexport class MemoryLeakError extends Error {\n constructor(\n public readonly emitter: Emitter,\n public readonly type: string | number | symbol,\n public readonly count: number\n ) {\n super(\n `Possible EventEmitter memory leak detected. ${count} ${type.toString()} listeners added. Use emitter.setMaxListeners() to increase limit`\n )\n this.name = 'MaxListenersExceededWarning'\n }\n}\n","import { MemoryLeakError } from './MemoryLeakError'\n\nexport type EventMap = {\n [eventName: string]: Array\n}\n\nexport type InternalEventNames = 'newListener' | 'removeListener'\n\nexport type InternalListener = Listener<\n [eventName: keyof Events, listener: Listener>]\n>\n\nexport type Listener> = (...data: Data) => void\n\n/**\n * Node.js-compatible implementation of `EventEmitter`.\n *\n * @example\n * const emitter = new Emitter<{ hello: [string] }>()\n * emitter.on('hello', (name) => console.log(name))\n * emitter.emit('hello', 'John')\n */\nexport class Emitter {\n private events: Map>>\n private maxListeners: number\n private hasWarnedAboutPotentialMemoryLeak: boolean\n\n static defaultMaxListeners = 10\n\n static listenerCount(\n emitter: Emitter,\n eventName: keyof Events\n ): number {\n return emitter.listenerCount(eventName)\n }\n\n constructor() {\n this.events = new Map()\n this.maxListeners = Emitter.defaultMaxListeners\n this.hasWarnedAboutPotentialMemoryLeak = false\n }\n\n private _emitInternalEvent(\n internalEventName: InternalEventNames,\n eventName: keyof Events,\n listener: Listener>\n ): void {\n this.emit(\n internalEventName,\n // Anything to make TypeScript happy.\n ...([eventName, listener] as Events['newListener'] &\n Events['removeListener'])\n )\n }\n\n private _getListeners(\n eventName: EventName\n ): Array>> {\n // Always return a copy of the listeners array\n // so they are fixed at the time of the \"_getListeners\" call.\n return Array.prototype.concat.apply([], this.events.get(eventName)) || []\n }\n\n private _removeListener(\n listeners: Array>,\n listener: Listener\n ): Array> {\n const index = listeners.indexOf(listener)\n\n if (index > -1) {\n listeners.splice(index, 1)\n }\n\n return []\n }\n\n private _wrapOnceListener(\n eventName: EventName,\n listener: Listener\n ): Listener {\n const onceListener = (...data: Events[keyof Events]) => {\n this.removeListener(eventName, onceListener)\n\n /**\n * @note Return the result of the original listener.\n * This way this wrapped preserves listeners that are async.\n */\n return listener.apply(this, data)\n }\n\n // Inherit the name of the original listener.\n Object.defineProperty(onceListener, 'name', { value: listener.name })\n\n return onceListener\n }\n\n public setMaxListeners(maxListeners: number): this {\n this.maxListeners = maxListeners\n return this\n }\n\n /**\n * Returns the current max listener value for the `Emitter` which is\n * either set by `emitter.setMaxListeners(n)` or defaults to\n * `Emitter.defaultMaxListeners`.\n */\n public getMaxListeners(): number {\n return this.maxListeners\n }\n\n /**\n * Returns an array listing the events for which the emitter has registered listeners.\n * The values in the array will be strings or Symbols.\n */\n public eventNames(): Array {\n return Array.from(this.events.keys())\n }\n\n /**\n * Synchronously calls each of the listeners registered for the event named `eventName`,\n * in the order they were registered, passing the supplied arguments to each.\n * Returns `true` if the event has listeners, `false` otherwise.\n *\n * @example\n * const emitter = new Emitter<{ hello: [string] }>()\n * emitter.emit('hello', 'John')\n */\n public emit(\n eventName: EventName,\n ...data: Events[EventName]\n ): boolean {\n const listeners = this._getListeners(eventName)\n listeners.forEach((listener) => {\n listener.apply(this, data)\n })\n\n return listeners.length > 0\n }\n\n public addListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public addListener(\n eventName: EventName,\n listener: Listener\n ): this\n public addListener(\n eventName: InternalEventNames | keyof Events,\n listener: InternalListener | Listener\n ): this {\n // Emit the `newListener` event before adding the listener.\n this._emitInternalEvent('newListener', eventName, listener)\n\n const nextListeners = this._getListeners(eventName).concat(listener)\n this.events.set(eventName, nextListeners)\n\n if (\n this.maxListeners > 0 &&\n this.listenerCount(eventName) > this.maxListeners &&\n !this.hasWarnedAboutPotentialMemoryLeak\n ) {\n this.hasWarnedAboutPotentialMemoryLeak = true\n\n const memoryLeakWarning = new MemoryLeakError(\n this,\n eventName,\n this.listenerCount(eventName)\n )\n console.warn(memoryLeakWarning)\n }\n\n return this\n }\n\n public on(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public on(\n eventName: EventName,\n listener: Listener\n ): this\n public on(\n eventName: 'removeListener' | EventName,\n listener: Listener\n ): this {\n return this.addListener(eventName, listener)\n }\n\n public once(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public once(\n eventName: EventName,\n listener: Listener\n ): this\n public once(\n eventName: InternalEventNames | EventName,\n listener: Listener\n ): this {\n return this.addListener(\n eventName,\n this._wrapOnceListener(eventName, listener)\n )\n }\n\n public prependListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public prependListener(\n eventName: EventName,\n listener: Listener\n ): this\n public prependListener(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n const listeners = this._getListeners(eventName)\n\n if (listeners.length > 0) {\n const nextListeners = [listener].concat(listeners)\n this.events.set(eventName, nextListeners)\n } else {\n this.events.set(eventName, listeners.concat(listener))\n }\n\n return this\n }\n\n public prependOnceListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public prependOnceListener(\n eventName: EventName,\n listener: Listener\n ): this\n public prependOnceListener(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n return this.prependListener(\n eventName,\n this._wrapOnceListener(eventName, listener)\n )\n }\n\n public removeListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public removeListener(\n eventName: EventName,\n listener: Listener\n ): this\n public removeListener(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n const listeners = this._getListeners(eventName)\n\n if (listeners.length > 0) {\n this._removeListener(listeners, listener)\n this.events.set(eventName, listeners)\n\n // Emit the `removeListener` event after removing the listener.\n this._emitInternalEvent('removeListener', eventName, listener)\n }\n\n return this\n }\n\n public off(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public off(\n eventName: EventName,\n listener: Listener\n ): this\n /**\n * Alias for `emitter.removeListener()`.\n *\n * @example\n * emitter.off('hello', listener)\n */\n public off(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n return this.removeListener(eventName, listener)\n }\n\n public removeAllListeners(eventName?: InternalEventNames): this\n public removeAllListeners(\n eventName?: EventName\n ): this\n public removeAllListeners(\n eventName?: InternalEventNames | keyof Events\n ): this {\n if (eventName) {\n this.events.delete(eventName)\n } else {\n this.events.clear()\n }\n\n return this\n }\n\n public listeners(eventName: InternalEventNames): Array>\n public listeners(\n eventName: EventName\n ): Array>\n /**\n * Returns a copy of the array of listeners for the event named `eventName`.\n */\n public listeners(eventName: InternalEventNames | keyof Events) {\n return Array.from(this._getListeners(eventName))\n }\n\n public listenerCount(eventName: InternalEventNames): number\n public listenerCount(\n eventName: EventName\n ): number\n /**\n * Returns the number of listeners listening to the event named `eventName`.\n */\n public listenerCount(eventName: InternalEventNames | keyof Events): number {\n return this._getListeners(eventName).length\n }\n\n public rawListeners(\n eventName: EventName\n ): Array> {\n return this.listeners(eventName)\n }\n}\n"],"mappings":"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","names":[]} \ No newline at end of file diff --git a/node_modules/strict-event-emitter/lib/index.mjs b/node_modules/strict-event-emitter/lib/index.mjs new file mode 100644 index 0000000000..d68faf8261 --- /dev/null +++ b/node_modules/strict-event-emitter/lib/index.mjs @@ -0,0 +1,171 @@ +// src/MemoryLeakError.ts +var MemoryLeakError = class extends Error { + constructor(emitter, type, count) { + super( + `Possible EventEmitter memory leak detected. ${count} ${type.toString()} listeners added. Use emitter.setMaxListeners() to increase limit` + ); + this.emitter = emitter; + this.type = type; + this.count = count; + this.name = "MaxListenersExceededWarning"; + } +}; + +// src/Emitter.ts +var _Emitter = class { + static listenerCount(emitter, eventName) { + return emitter.listenerCount(eventName); + } + constructor() { + this.events = /* @__PURE__ */ new Map(); + this.maxListeners = _Emitter.defaultMaxListeners; + this.hasWarnedAboutPotentialMemoryLeak = false; + } + _emitInternalEvent(internalEventName, eventName, listener) { + this.emit( + internalEventName, + ...[eventName, listener] + ); + } + _getListeners(eventName) { + return Array.prototype.concat.apply([], this.events.get(eventName)) || []; + } + _removeListener(listeners, listener) { + const index = listeners.indexOf(listener); + if (index > -1) { + listeners.splice(index, 1); + } + return []; + } + _wrapOnceListener(eventName, listener) { + const onceListener = (...data) => { + this.removeListener(eventName, onceListener); + return listener.apply(this, data); + }; + Object.defineProperty(onceListener, "name", { value: listener.name }); + return onceListener; + } + setMaxListeners(maxListeners) { + this.maxListeners = maxListeners; + return this; + } + /** + * Returns the current max listener value for the `Emitter` which is + * either set by `emitter.setMaxListeners(n)` or defaults to + * `Emitter.defaultMaxListeners`. + */ + getMaxListeners() { + return this.maxListeners; + } + /** + * Returns an array listing the events for which the emitter has registered listeners. + * The values in the array will be strings or Symbols. + */ + eventNames() { + return Array.from(this.events.keys()); + } + /** + * Synchronously calls each of the listeners registered for the event named `eventName`, + * in the order they were registered, passing the supplied arguments to each. + * Returns `true` if the event has listeners, `false` otherwise. + * + * @example + * const emitter = new Emitter<{ hello: [string] }>() + * emitter.emit('hello', 'John') + */ + emit(eventName, ...data) { + const listeners = this._getListeners(eventName); + listeners.forEach((listener) => { + listener.apply(this, data); + }); + return listeners.length > 0; + } + addListener(eventName, listener) { + this._emitInternalEvent("newListener", eventName, listener); + const nextListeners = this._getListeners(eventName).concat(listener); + this.events.set(eventName, nextListeners); + if (this.maxListeners > 0 && this.listenerCount(eventName) > this.maxListeners && !this.hasWarnedAboutPotentialMemoryLeak) { + this.hasWarnedAboutPotentialMemoryLeak = true; + const memoryLeakWarning = new MemoryLeakError( + this, + eventName, + this.listenerCount(eventName) + ); + console.warn(memoryLeakWarning); + } + return this; + } + on(eventName, listener) { + return this.addListener(eventName, listener); + } + once(eventName, listener) { + return this.addListener( + eventName, + this._wrapOnceListener(eventName, listener) + ); + } + prependListener(eventName, listener) { + const listeners = this._getListeners(eventName); + if (listeners.length > 0) { + const nextListeners = [listener].concat(listeners); + this.events.set(eventName, nextListeners); + } else { + this.events.set(eventName, listeners.concat(listener)); + } + return this; + } + prependOnceListener(eventName, listener) { + return this.prependListener( + eventName, + this._wrapOnceListener(eventName, listener) + ); + } + removeListener(eventName, listener) { + const listeners = this._getListeners(eventName); + if (listeners.length > 0) { + this._removeListener(listeners, listener); + this.events.set(eventName, listeners); + this._emitInternalEvent("removeListener", eventName, listener); + } + return this; + } + /** + * Alias for `emitter.removeListener()`. + * + * @example + * emitter.off('hello', listener) + */ + off(eventName, listener) { + return this.removeListener(eventName, listener); + } + removeAllListeners(eventName) { + if (eventName) { + this.events.delete(eventName); + } else { + this.events.clear(); + } + return this; + } + /** + * Returns a copy of the array of listeners for the event named `eventName`. + */ + listeners(eventName) { + return Array.from(this._getListeners(eventName)); + } + /** + * Returns the number of listeners listening to the event named `eventName`. + */ + listenerCount(eventName) { + return this._getListeners(eventName).length; + } + rawListeners(eventName) { + return this.listeners(eventName); + } +}; +var Emitter = _Emitter; +Emitter.defaultMaxListeners = 10; +export { + Emitter, + MemoryLeakError +}; +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/node_modules/strict-event-emitter/lib/index.mjs.map b/node_modules/strict-event-emitter/lib/index.mjs.map new file mode 100644 index 0000000000..26936046f3 --- /dev/null +++ b/node_modules/strict-event-emitter/lib/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/MemoryLeakError.ts","../src/Emitter.ts"],"sourcesContent":["import type { Emitter } from './Emitter'\n\nexport class MemoryLeakError extends Error {\n constructor(\n public readonly emitter: Emitter,\n public readonly type: string | number | symbol,\n public readonly count: number\n ) {\n super(\n `Possible EventEmitter memory leak detected. ${count} ${type.toString()} listeners added. Use emitter.setMaxListeners() to increase limit`\n )\n this.name = 'MaxListenersExceededWarning'\n }\n}\n","import { MemoryLeakError } from './MemoryLeakError'\n\nexport type EventMap = {\n [eventName: string]: Array\n}\n\nexport type InternalEventNames = 'newListener' | 'removeListener'\n\nexport type InternalListener = Listener<\n [eventName: keyof Events, listener: Listener>]\n>\n\nexport type Listener> = (...data: Data) => void\n\n/**\n * Node.js-compatible implementation of `EventEmitter`.\n *\n * @example\n * const emitter = new Emitter<{ hello: [string] }>()\n * emitter.on('hello', (name) => console.log(name))\n * emitter.emit('hello', 'John')\n */\nexport class Emitter {\n private events: Map>>\n private maxListeners: number\n private hasWarnedAboutPotentialMemoryLeak: boolean\n\n static defaultMaxListeners = 10\n\n static listenerCount(\n emitter: Emitter,\n eventName: keyof Events\n ): number {\n return emitter.listenerCount(eventName)\n }\n\n constructor() {\n this.events = new Map()\n this.maxListeners = Emitter.defaultMaxListeners\n this.hasWarnedAboutPotentialMemoryLeak = false\n }\n\n private _emitInternalEvent(\n internalEventName: InternalEventNames,\n eventName: keyof Events,\n listener: Listener>\n ): void {\n this.emit(\n internalEventName,\n // Anything to make TypeScript happy.\n ...([eventName, listener] as Events['newListener'] &\n Events['removeListener'])\n )\n }\n\n private _getListeners(\n eventName: EventName\n ): Array>> {\n // Always return a copy of the listeners array\n // so they are fixed at the time of the \"_getListeners\" call.\n return Array.prototype.concat.apply([], this.events.get(eventName)) || []\n }\n\n private _removeListener(\n listeners: Array>,\n listener: Listener\n ): Array> {\n const index = listeners.indexOf(listener)\n\n if (index > -1) {\n listeners.splice(index, 1)\n }\n\n return []\n }\n\n private _wrapOnceListener(\n eventName: EventName,\n listener: Listener\n ): Listener {\n const onceListener = (...data: Events[keyof Events]) => {\n this.removeListener(eventName, onceListener)\n\n /**\n * @note Return the result of the original listener.\n * This way this wrapped preserves listeners that are async.\n */\n return listener.apply(this, data)\n }\n\n // Inherit the name of the original listener.\n Object.defineProperty(onceListener, 'name', { value: listener.name })\n\n return onceListener\n }\n\n public setMaxListeners(maxListeners: number): this {\n this.maxListeners = maxListeners\n return this\n }\n\n /**\n * Returns the current max listener value for the `Emitter` which is\n * either set by `emitter.setMaxListeners(n)` or defaults to\n * `Emitter.defaultMaxListeners`.\n */\n public getMaxListeners(): number {\n return this.maxListeners\n }\n\n /**\n * Returns an array listing the events for which the emitter has registered listeners.\n * The values in the array will be strings or Symbols.\n */\n public eventNames(): Array {\n return Array.from(this.events.keys())\n }\n\n /**\n * Synchronously calls each of the listeners registered for the event named `eventName`,\n * in the order they were registered, passing the supplied arguments to each.\n * Returns `true` if the event has listeners, `false` otherwise.\n *\n * @example\n * const emitter = new Emitter<{ hello: [string] }>()\n * emitter.emit('hello', 'John')\n */\n public emit(\n eventName: EventName,\n ...data: Events[EventName]\n ): boolean {\n const listeners = this._getListeners(eventName)\n listeners.forEach((listener) => {\n listener.apply(this, data)\n })\n\n return listeners.length > 0\n }\n\n public addListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public addListener(\n eventName: EventName,\n listener: Listener\n ): this\n public addListener(\n eventName: InternalEventNames | keyof Events,\n listener: InternalListener | Listener\n ): this {\n // Emit the `newListener` event before adding the listener.\n this._emitInternalEvent('newListener', eventName, listener)\n\n const nextListeners = this._getListeners(eventName).concat(listener)\n this.events.set(eventName, nextListeners)\n\n if (\n this.maxListeners > 0 &&\n this.listenerCount(eventName) > this.maxListeners &&\n !this.hasWarnedAboutPotentialMemoryLeak\n ) {\n this.hasWarnedAboutPotentialMemoryLeak = true\n\n const memoryLeakWarning = new MemoryLeakError(\n this,\n eventName,\n this.listenerCount(eventName)\n )\n console.warn(memoryLeakWarning)\n }\n\n return this\n }\n\n public on(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public on(\n eventName: EventName,\n listener: Listener\n ): this\n public on(\n eventName: 'removeListener' | EventName,\n listener: Listener\n ): this {\n return this.addListener(eventName, listener)\n }\n\n public once(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public once(\n eventName: EventName,\n listener: Listener\n ): this\n public once(\n eventName: InternalEventNames | EventName,\n listener: Listener\n ): this {\n return this.addListener(\n eventName,\n this._wrapOnceListener(eventName, listener)\n )\n }\n\n public prependListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public prependListener(\n eventName: EventName,\n listener: Listener\n ): this\n public prependListener(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n const listeners = this._getListeners(eventName)\n\n if (listeners.length > 0) {\n const nextListeners = [listener].concat(listeners)\n this.events.set(eventName, nextListeners)\n } else {\n this.events.set(eventName, listeners.concat(listener))\n }\n\n return this\n }\n\n public prependOnceListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public prependOnceListener(\n eventName: EventName,\n listener: Listener\n ): this\n public prependOnceListener(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n return this.prependListener(\n eventName,\n this._wrapOnceListener(eventName, listener)\n )\n }\n\n public removeListener(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public removeListener(\n eventName: EventName,\n listener: Listener\n ): this\n public removeListener(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n const listeners = this._getListeners(eventName)\n\n if (listeners.length > 0) {\n this._removeListener(listeners, listener)\n this.events.set(eventName, listeners)\n\n // Emit the `removeListener` event after removing the listener.\n this._emitInternalEvent('removeListener', eventName, listener)\n }\n\n return this\n }\n\n public off(\n eventName: InternalEventNames,\n listener: InternalListener\n ): this\n public off(\n eventName: EventName,\n listener: Listener\n ): this\n /**\n * Alias for `emitter.removeListener()`.\n *\n * @example\n * emitter.off('hello', listener)\n */\n public off(\n eventName: InternalEventNames | keyof Events,\n listener: Listener\n ): this {\n return this.removeListener(eventName, listener)\n }\n\n public removeAllListeners(eventName?: InternalEventNames): this\n public removeAllListeners(\n eventName?: EventName\n ): this\n public removeAllListeners(\n eventName?: InternalEventNames | keyof Events\n ): this {\n if (eventName) {\n this.events.delete(eventName)\n } else {\n this.events.clear()\n }\n\n return this\n }\n\n public listeners(eventName: InternalEventNames): Array>\n public listeners(\n eventName: EventName\n ): Array>\n /**\n * Returns a copy of the array of listeners for the event named `eventName`.\n */\n public listeners(eventName: InternalEventNames | keyof Events) {\n return Array.from(this._getListeners(eventName))\n }\n\n public listenerCount(eventName: InternalEventNames): number\n public listenerCount(\n eventName: EventName\n ): number\n /**\n * Returns the number of listeners listening to the event named `eventName`.\n */\n public listenerCount(eventName: InternalEventNames | keyof Events): number {\n return this._getListeners(eventName).length\n }\n\n public rawListeners(\n eventName: EventName\n ): Array> {\n return this.listeners(eventName)\n }\n}\n"],"mappings":"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","names":[]} \ No newline at end of file diff --git a/node_modules/strict-event-emitter/package.json b/node_modules/strict-event-emitter/package.json new file mode 100644 index 0000000000..54a40577dd --- /dev/null +++ b/node_modules/strict-event-emitter/package.json @@ -0,0 +1,41 @@ +{ + "name": "strict-event-emitter", + "version": "0.5.1", + "description": "Type-safe implementation of EventEmitter for browser and Node.js", + "main": "lib/index.js", + "module": "lib/index.mjs", + "typings": "lib/index.d.ts", + "exports": { + ".": { + "types": "./lib/index.d.ts", + "require": "./lib/index.js", + "default": "./lib/index.mjs" + } + }, + "repository": "git@github.com:open-draft/strict-event-emitter.git", + "author": "Artem Zakharchenko ", + "license": "MIT", + "files": [ + "lib" + ], + "devDependencies": { + "@ossjs/release": "^0.8.0", + "@types/events": "^3.0.0", + "@types/jest": "^29.2.4", + "jest": "^29.3.1", + "jest-extended": "^3.2.0", + "rimraf": "^3.0.2", + "ts-jest": "^29.0.3", + "ts-node": "^9.1.1", + "tsup": "^6.2.3", + "typescript": "4.8" + }, + "scripts": { + "dev": "tsc -w", + "test": "jest", + "test:ts": "tsc -p test/typings.tsconfig.json", + "clean": "rimraf ./lib", + "build": "pnpm clean && tsup", + "release": "release publish" + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e4b0c119d5..b34e41be0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codeql", - "version": "3.28.5", + "version": "3.28.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codeql", - "version": "3.28.5", + "version": "3.28.6", "license": "MIT", "dependencies": { "@actions/artifact": "^2.1.9", @@ -46,7 +46,7 @@ "@ava/typescript": "4.1.0", "@eslint/compat": "^1.1.1", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.18.0", + "@eslint/js": "^9.19.0", "@microsoft/eslint-formatter-sarif": "^3.1.0", "@types/adm-zip": "^0.5.7", "@types/console-log-level": "^1.4.5", @@ -56,8 +56,8 @@ "@types/node": "20.9.0", "@types/semver": "^7.5.8", "@types/sinon": "^17.0.3", - "@typescript-eslint/eslint-plugin": "^8.21.0", - "@typescript-eslint/parser": "^8.21.0", + "@typescript-eslint/eslint-plugin": "^8.22.0", + "@typescript-eslint/parser": "^8.22.0", "ava": "^5.3.1", "eslint": "^8.57.1", "eslint-import-resolver-typescript": "^3.7.0", @@ -66,7 +66,7 @@ "eslint-plugin-import": "2.29.1", "eslint-plugin-no-async-foreach": "^0.1.1", "micromatch": "4.0.8", - "nock": "^13.5.6", + "nock": "^14.0.0", "removeNPMAbsolutePaths": "3.0.1", "sinon": "^19.0.2", "typescript": "^5.7.3" @@ -706,9 +706,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "dev": true, "license": "MIT", "engines": { @@ -861,6 +861,24 @@ "node": ">= 14" } }, + "node_modules/@mswjs/interceptors": { + "version": "0.37.5", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.5.tgz", + "integrity": "sha512-AAwRb5vXFcY4L+FvZ7LZusDuZ0vEe0Zm8ohn1FM6/X7A3bj4mqmkAcGRWuvC2JwSygNwHAAmMnAI73vPHeqsHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "license": "MIT", @@ -1129,6 +1147,31 @@ "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", "license": "MIT" }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1360,17 +1403,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz", - "integrity": "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.22.0.tgz", + "integrity": "sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/type-utils": "8.21.0", - "@typescript-eslint/utils": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/type-utils": "8.22.0", + "@typescript-eslint/utils": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1390,14 +1433,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", - "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1408,9 +1451,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", - "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "dev": true, "license": "MIT", "engines": { @@ -1422,14 +1465,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", - "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1449,16 +1492,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz", - "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", + "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/typescript-estree": "8.21.0" + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1473,13 +1516,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", - "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1543,16 +1586,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.21.0.tgz", - "integrity": "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.22.0.tgz", + "integrity": "sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/typescript-estree": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4" }, "engines": { @@ -1568,14 +1611,14 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", - "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1586,9 +1629,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", - "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "dev": true, "license": "MIT", "engines": { @@ -1600,14 +1643,14 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", - "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1627,13 +1670,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", - "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1715,14 +1758,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz", - "integrity": "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.22.0.tgz", + "integrity": "sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.21.0", - "@typescript-eslint/utils": "8.21.0", + "@typescript-eslint/typescript-estree": "8.22.0", + "@typescript-eslint/utils": "8.22.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, @@ -1739,14 +1782,14 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", - "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.22.0.tgz", + "integrity": "sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0" + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1757,9 +1800,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", - "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.22.0.tgz", + "integrity": "sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==", "dev": true, "license": "MIT", "engines": { @@ -1771,14 +1814,14 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", - "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.22.0.tgz", + "integrity": "sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/visitor-keys": "8.21.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/visitor-keys": "8.22.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1798,16 +1841,16 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz", - "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.22.0.tgz", + "integrity": "sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.21.0", - "@typescript-eslint/types": "8.21.0", - "@typescript-eslint/typescript-estree": "8.21.0" + "@typescript-eslint/scope-manager": "8.22.0", + "@typescript-eslint/types": "8.22.0", + "@typescript-eslint/typescript-estree": "8.22.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1822,13 +1865,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", - "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.22.0.tgz", + "integrity": "sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/types": "8.22.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -5228,6 +5271,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "license": "MIT", @@ -5871,17 +5921,18 @@ "license": "0BSD" }, "node_modules/nock": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", - "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.0.tgz", + "integrity": "sha512-3Z2ZoZoYTR/y2I+NI16+6IzfZFKBX7MrADtoBAm7v/QKqxQUhKw+Dh+847PPS1j/FDutjfIXfrh3CJF74yITWg==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.0", + "@mswjs/interceptors": "^0.37.3", "json-stringify-safe": "^5.0.1", "propagate": "^2.0.0" }, "engines": { - "node": ">= 10.13" + "node": ">= 18" } }, "node_modules/node-fetch": { @@ -6109,6 +6160,13 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, "node_modules/p-defer": { "version": "1.0.0", "dev": true, @@ -6953,6 +7011,13 @@ "bare-events": "^2.2.0" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 77400ece0c..df627fc4eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codeql", - "version": "3.28.5", + "version": "3.28.6", "private": true, "description": "CodeQL action", "scripts": { @@ -62,7 +62,7 @@ "@ava/typescript": "4.1.0", "@eslint/compat": "^1.1.1", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.18.0", + "@eslint/js": "^9.19.0", "@microsoft/eslint-formatter-sarif": "^3.1.0", "@types/adm-zip": "^0.5.7", "@types/console-log-level": "^1.4.5", @@ -72,8 +72,8 @@ "@types/node": "20.9.0", "@types/semver": "^7.5.8", "@types/sinon": "^17.0.3", - "@typescript-eslint/eslint-plugin": "^8.21.0", - "@typescript-eslint/parser": "^8.21.0", + "@typescript-eslint/eslint-plugin": "^8.22.0", + "@typescript-eslint/parser": "^8.22.0", "ava": "^5.3.1", "eslint": "^8.57.1", "eslint-import-resolver-typescript": "^3.7.0", @@ -82,7 +82,7 @@ "eslint-plugin-import": "2.29.1", "eslint-plugin-no-async-foreach": "^0.1.1", "micromatch": "4.0.8", - "nock": "^13.5.6", + "nock": "^14.0.0", "removeNPMAbsolutePaths": "3.0.1", "sinon": "^19.0.2", "typescript": "^5.7.3" diff --git a/pr-checks/checks/submit-sarif-failure.yml b/pr-checks/checks/submit-sarif-failure.yml index 7dd5ac76ba..0700428853 100644 --- a/pr-checks/checks/submit-sarif-failure.yml +++ b/pr-checks/checks/submit-sarif-failure.yml @@ -14,6 +14,10 @@ env: # Mark telemetry for this workflow so it can be treated separately. CODEQL_ACTION_TESTING_ENVIRONMENT: codeql-action-pr-checks +permissions: + contents: read + security-events: write # needed to upload the SARIF file + steps: - uses: actions/checkout@v4 - uses: ./init diff --git a/pr-checks/sync.py b/pr-checks/sync.py index 13ee591af9..f27dbdd8f3 100755 --- a/pr-checks/sync.py +++ b/pr-checks/sync.py @@ -126,7 +126,7 @@ def writeHeader(checkStream): 'name': checkSpecification['name'], 'permissions': { 'contents': 'read', - 'security-events': 'write' + 'security-events': 'read' }, 'timeout-minutes': 45, 'runs-on': '${{ matrix.os }}', diff --git a/src/analyze-action-post.ts b/src/analyze-action-post.ts index 5f457017db..eaa08a50d8 100644 --- a/src/analyze-action-post.ts +++ b/src/analyze-action-post.ts @@ -7,6 +7,7 @@ import * as core from "@actions/core"; import * as actionsUtil from "./actions-util"; import { getGitHubVersion } from "./api-client"; +import { getCodeQL } from "./codeql"; import { getConfig } from "./config-utils"; import * as debugArtifacts from "./debug-artifacts"; import { EnvVar } from "./environment"; @@ -28,10 +29,13 @@ async function runWrapper() { logger, ); if (config !== undefined) { + const codeql = await getCodeQL(config.codeQLCmd); + const version = await codeql.getVersion(); await withGroup("Uploading combined SARIF debug artifact", () => debugArtifacts.uploadCombinedSarifArtifacts( logger, config.gitHubVersion.type, + version.version, ), ); } diff --git a/src/debug-artifacts.test.ts b/src/debug-artifacts.test.ts index a61519105a..08f9a1d3e8 100644 --- a/src/debug-artifacts.test.ts +++ b/src/debug-artifacts.test.ts @@ -20,16 +20,92 @@ test("sanitizeArtifactName", (t) => { ); }); -test("uploadDebugArtifacts", async (t) => { +// These next tests check the correctness of the logic to determine whether or not +// artifacts are uploaded in debug mode. Since it's not easy to mock the actual +// call to upload an artifact, we just check that we get an "upload-failed" result, +// instead of actually uploading the artifact. +// +// For tests where we expect artifact upload to be blocked, we check for a different +// response from the function. + +test("uploadDebugArtifacts when artifacts empty should emit 'no-artifacts-to-upload'", async (t) => { // Test that no error is thrown if artifacts list is empty. const logger = getActionsLogger(); - await t.notThrowsAsync( - debugArtifacts.uploadDebugArtifacts( + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts( logger, [], - "rootDir", + "i-dont-exist", "artifactName", GitHubVariant.DOTCOM, - ), - ); + undefined, + ); + t.is( + uploaded, + "no-artifacts-to-upload", + "Should not have uploaded any artifacts", + ); + }); +}); + +test("uploadDebugArtifacts when no codeql version is used should invoke artifact upload", async (t) => { + // Test that the artifact is uploaded. + const logger = getActionsLogger(); + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts( + logger, + ["hucairz"], + "i-dont-exist", + "artifactName", + GitHubVariant.DOTCOM, + undefined, + ); + t.is( + uploaded, + // The failure is expected since we don't want to actually upload any artifacts in unit tests. + "upload-failed", + "Expect failure to upload artifacts since root dir does not exist", + ); + }); +}); + +test("uploadDebugArtifacts when new codeql version is used should invoke artifact upload", async (t) => { + // Test that the artifact is uploaded. + const logger = getActionsLogger(); + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts( + logger, + ["hucairz"], + "i-dont-exist", + "artifactName", + GitHubVariant.DOTCOM, + "2.20.3", + ); + t.is( + uploaded, + // The failure is expected since we don't want to actually upload any artifacts in unit tests. + "upload-failed", + "Expect failure to upload artifacts since root dir does not exist", + ); + }); +}); + +test("uploadDebugArtifacts when old codeql is used should avoid trying to upload artifacts", async (t) => { + // Test that the artifact is not uploaded. + const logger = getActionsLogger(); + await t.notThrowsAsync(async () => { + const uploaded = await debugArtifacts.uploadDebugArtifacts( + logger, + ["hucairz"], + "i-dont-exist", + "artifactName", + GitHubVariant.DOTCOM, + "2.20.2", + ); + t.is( + uploaded, + "upload-not-supported", + "Expected artifact upload to be blocked because of old CodeQL version", + ); + }); }); diff --git a/src/debug-artifacts.ts b/src/debug-artifacts.ts index a15277a7b8..a7c23784f4 100644 --- a/src/debug-artifacts.ts +++ b/src/debug-artifacts.ts @@ -7,13 +7,17 @@ import * as core from "@actions/core"; import AdmZip from "adm-zip"; import del from "del"; -import { getRequiredInput, getTemporaryDirectory } from "./actions-util"; +import { getOptionalInput, getTemporaryDirectory } from "./actions-util"; import { dbIsFinalized } from "./analyze"; import { getCodeQL } from "./codeql"; import { Config } from "./config-utils"; import { EnvVar } from "./environment"; import { Language } from "./languages"; import { Logger, withGroup } from "./logging"; +import { + isSafeArtifactUpload, + SafeArtifactUploadVersion, +} from "./tools-features"; import { bundleDb, doesDirectoryExist, @@ -34,6 +38,7 @@ export function sanitizeArtifactName(name: string): string { export async function uploadCombinedSarifArtifacts( logger: Logger, gitHubVariant: GitHubVariant, + codeQlVersion: string | undefined, ) { const tempDir = getTemporaryDirectory(); @@ -68,6 +73,7 @@ export async function uploadCombinedSarifArtifacts( baseTempDir, "combined-sarif-artifacts", gitHubVariant, + codeQlVersion, ); } catch (e) { logger.warning( @@ -160,6 +166,7 @@ async function tryBundleDatabase( export async function tryUploadAllAvailableDebugArtifacts( config: Config, logger: Logger, + codeQlVersion: string | undefined, ) { const filesToUpload: string[] = []; try { @@ -223,6 +230,7 @@ export async function tryUploadAllAvailableDebugArtifacts( config.dbLocation, config.debugArtifactName, config.gitHubVersion.type, + codeQlVersion, ), ); } catch (e) { @@ -238,15 +246,27 @@ export async function uploadDebugArtifacts( rootDir: string, artifactName: string, ghVariant: GitHubVariant, -) { + codeQlVersion: string | undefined, +): Promise< + | "no-artifacts-to-upload" + | "upload-successful" + | "upload-failed" + | "upload-not-supported" +> { if (toUpload.length === 0) { - return; + return "no-artifacts-to-upload"; + } + const uploadSupported = isSafeArtifactUpload(codeQlVersion); + + if (!uploadSupported) { + core.info( + `Skipping debug artifact upload because the current CLI does not support safe upload. Please upgrade to CLI v${SafeArtifactUploadVersion} or later.`, + ); + return "upload-not-supported"; } - logger.info("Uploading debug artifacts is temporarily disabled"); - return; let suffix = ""; - const matrix = getRequiredInput("matrix"); + const matrix = getOptionalInput("matrix"); if (matrix) { try { for (const [, matrixVal] of Object.entries( @@ -272,9 +292,11 @@ export async function uploadDebugArtifacts( retentionDays: 7, }, ); + return "upload-successful"; } catch (e) { // A failure to upload debug artifacts should not fail the entire action. core.warning(`Failed to upload debug artifacts: ${e}`); + return "upload-failed"; } } diff --git a/src/init-action-post-helper.ts b/src/init-action-post-helper.ts index 2fa1774b4e..78aa40f19f 100644 --- a/src/init-action-post-helper.ts +++ b/src/init-action-post-helper.ts @@ -161,7 +161,7 @@ export async function run( uploadAllAvailableDebugArtifacts: ( config: Config, logger: Logger, - features: FeatureEnablement, + codeQlVersion: string, ) => Promise, printDebugLogs: (config: Config) => Promise, config: Config, @@ -211,7 +211,9 @@ export async function run( logger.info( "Debug mode is on. Uploading available database bundles and logs as Actions debugging artifacts...", ); - await uploadAllAvailableDebugArtifacts(config, logger, features); + const codeql = await getCodeQL(config.codeQLCmd); + const version = await codeql.getVersion(); + await uploadAllAvailableDebugArtifacts(config, logger, version.version); await printDebugLogs(config); } diff --git a/src/start-proxy-action.ts b/src/start-proxy-action.ts index 0cbfcf7173..013b237bad 100644 --- a/src/start-proxy-action.ts +++ b/src/start-proxy-action.ts @@ -6,8 +6,8 @@ import * as toolcache from "@actions/tool-cache"; import { pki } from "node-forge"; import * as actionsUtil from "./actions-util"; -import { Language, parseLanguage } from "./languages"; import { getActionsLogger, Logger } from "./logging"; +import { Credential, getCredentials } from "./start-proxy"; import * as util from "./util"; const UPDATEJOB_PROXY = "update-job-proxy"; @@ -18,34 +18,11 @@ const PROXY_USER = "proxy_user"; const KEY_SIZE = 2048; const KEY_EXPIRY_YEARS = 2; -const LANGUAGE_TO_REGISTRY_TYPE: Record = { - java: "maven_repository", - csharp: "nuget_feed", - javascript: "npm_registry", - python: "python_index", - ruby: "rubygems_server", - rust: "cargo_registry", - // We do not have an established proxy type for these languages, thus leaving empty. - actions: "", - cpp: "", - go: "", - swift: "", -} as const; - type CertificateAuthority = { cert: string; key: string; }; -type Credential = { - type: string; - host?: string; - url?: string; - username?: string; - password?: string; - token?: string; -}; - type BasicAuthCredentials = { username: string; password: string; @@ -117,7 +94,12 @@ async function runWrapper() { core.saveState("proxy-log-file", proxyLogFilePath); // Get the configuration options - const credentials = getCredentials(logger); + const credentials = getCredentials( + logger, + actionsUtil.getOptionalInput("registry_secrets"), + actionsUtil.getOptionalInput("registries_credentials"), + actionsUtil.getOptionalInput("language"), + ); logger.info( `Credentials loaded for the following registries:\n ${credentials .map((c) => credentialToStr(c)) @@ -199,58 +181,6 @@ async function startProxy( } } -// getCredentials returns registry credentials from action inputs. -// It prefers `registries_credentials` over `registry_secrets`. -// If neither is set, it returns an empty array. -function getCredentials(logger: Logger): Credential[] { - const registriesCredentials = actionsUtil.getOptionalInput( - "registries_credentials", - ); - const registrySecrets = actionsUtil.getOptionalInput("registry_secrets"); - const languageString = actionsUtil.getOptionalInput("language"); - const language = languageString ? parseLanguage(languageString) : undefined; - const registryTypeForLanguage = language - ? LANGUAGE_TO_REGISTRY_TYPE[language] - : undefined; - - let credentialsStr: string; - if (registriesCredentials !== undefined) { - logger.info(`Using registries_credentials input.`); - credentialsStr = Buffer.from(registriesCredentials, "base64").toString(); - } else if (registrySecrets !== undefined) { - logger.info(`Using registry_secrets input.`); - credentialsStr = registrySecrets; - } else { - logger.info(`No credentials defined.`); - return []; - } - - // Parse and validate the credentials - const parsed = JSON.parse(credentialsStr) as Credential[]; - const out: Credential[] = []; - for (const e of parsed) { - if (e.url === undefined && e.host === undefined) { - throw new Error("Invalid credentials - must specify host or url"); - } - - // Filter credentials based on language if specified. `type` is the registry type. - // E.g., "maven_feed" for Java/Kotlin, "nuget_repository" for C#. - if (e.type !== registryTypeForLanguage) { - continue; - } - - out.push({ - type: e.type, - host: e.host, - url: e.url, - username: e.username, - password: e.password, - token: e.token, - }); - } - return out; -} - // getProxyAuth returns the authentication information for the proxy itself. function getProxyAuth(): BasicAuthCredentials | undefined { const proxy_password = actionsUtil.getOptionalInput("proxy_password"); diff --git a/src/start-proxy.test.ts b/src/start-proxy.test.ts new file mode 100644 index 0000000000..cb84833cc6 --- /dev/null +++ b/src/start-proxy.test.ts @@ -0,0 +1,115 @@ +import test from "ava"; + +import { getRunnerLogger } from "./logging"; +import * as startProxyExports from "./start-proxy"; +import { setupTests } from "./testing-utils"; + +setupTests(test); + +test("getCredentials prefers registriesCredentials over registrySecrets", async (t) => { + const registryCredentials = Buffer.from( + JSON.stringify([ + { type: "npm_registry", host: "npm.pkg.github.com", token: "abc" }, + ]), + ).toString("base64"); + const registrySecrets = JSON.stringify([ + { type: "npm_registry", host: "registry.npmjs.org", token: "def" }, + ]); + + const credentials = startProxyExports.getCredentials( + getRunnerLogger(true), + registrySecrets, + registryCredentials, + undefined, + ); + t.is(credentials.length, 1); + t.is(credentials[0].host, "npm.pkg.github.com"); +}); + +test("getCredentials throws error when credential missing host and url", async (t) => { + const registryCredentials = Buffer.from( + JSON.stringify([{ type: "npm_registry", token: "abc" }]), + ).toString("base64"); + + t.throws( + () => + startProxyExports.getCredentials( + getRunnerLogger(true), + undefined, + registryCredentials, + undefined, + ), + { + message: "Invalid credentials - must specify host or url", + }, + ); +}); + +test("getCredentials filters by language when specified", async (t) => { + const mixedCredentials = [ + { type: "npm_registry", host: "npm.pkg.github.com", token: "abc" }, + { type: "maven_repository", host: "maven.pkg.github.com", token: "def" }, + { type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" }, + ]; + + const credentials = startProxyExports.getCredentials( + getRunnerLogger(true), + undefined, + Buffer.from(JSON.stringify(mixedCredentials)).toString("base64"), + "java", + ); + t.is(credentials.length, 1); + t.is(credentials[0].type, "maven_repository"); +}); + +test("getCredentials returns all credentials when no language specified", async (t) => { + const mixedCredentials = [ + { type: "npm_registry", host: "npm.pkg.github.com", token: "abc" }, + { type: "maven_repository", host: "maven.pkg.github.com", token: "def" }, + { type: "nuget_feed", host: "nuget.pkg.github.com", token: "ghi" }, + ]; + const credentialsInput = Buffer.from( + JSON.stringify(mixedCredentials), + ).toString("base64"); + + const credentials = startProxyExports.getCredentials( + getRunnerLogger(true), + undefined, + credentialsInput, + undefined, + ); + t.is(credentials.length, 3); +}); + +test("getCredentials throws an error when non-printable characters are used", async (t) => { + const invalidCredentials = [ + { type: "nuget_feed", host: "1nuget.pkg.github.com", token: "abc\u0000" }, // Non-printable character in token + { type: "nuget_feed", host: "2nuget.pkg.github.com\u0001" }, // Non-printable character in host + { + type: "nuget_feed", + host: "3nuget.pkg.github.com", + password: "ghi\u0002", + }, // Non-printable character in password + { type: "nuget_feed", host: "4nuget.pkg.github.com", password: "ghi\x00" }, // Non-printable character in password + ]; + + for (const invalidCredential of invalidCredentials) { + const credentialsInput = Buffer.from( + JSON.stringify([invalidCredential]), + ).toString("base64"); + + t.throws( + () => + startProxyExports.getCredentials( + getRunnerLogger(true), + undefined, + credentialsInput, + undefined, + ), + { + message: + "Invalid credentials - fields must contain only printable characters", + }, + ); + } +}); diff --git a/src/start-proxy.ts b/src/start-proxy.ts new file mode 100644 index 0000000000..51c6f2fc07 --- /dev/null +++ b/src/start-proxy.ts @@ -0,0 +1,106 @@ +import { parseLanguage, Language } from "./languages"; +import { Logger } from "./logging"; +import { ConfigurationError } from "./util"; + +export type Credential = { + type: string; + host?: string; + url?: string; + username?: string; + password?: string; + token?: string; +}; + +const LANGUAGE_TO_REGISTRY_TYPE: Record = { + java: "maven_repository", + csharp: "nuget_feed", + javascript: "npm_registry", + python: "python_index", + ruby: "rubygems_server", + rust: "cargo_registry", + // We do not have an established proxy type for these languages, thus leaving empty. + actions: "", + cpp: "", + go: "", + swift: "", +} as const; + +// getCredentials returns registry credentials from action inputs. +// It prefers `registries_credentials` over `registry_secrets`. +// If neither is set, it returns an empty array. +export function getCredentials( + logger: Logger, + registrySecrets: string | undefined, + registriesCredentials: string | undefined, + languageString: string | undefined, +): Credential[] { + const language = languageString ? parseLanguage(languageString) : undefined; + const registryTypeForLanguage = language + ? LANGUAGE_TO_REGISTRY_TYPE[language] + : undefined; + + let credentialsStr: string; + if (registriesCredentials !== undefined) { + logger.info(`Using registries_credentials input.`); + credentialsStr = Buffer.from(registriesCredentials, "base64").toString(); + } else if (registrySecrets !== undefined) { + logger.info(`Using registry_secrets input.`); + credentialsStr = registrySecrets; + } else { + logger.info(`No credentials defined.`); + return []; + } + + // Parse and validate the credentials + let parsed: Credential[]; + try { + parsed = JSON.parse(credentialsStr) as Credential[]; + } catch { + // Don't log the error since it might contain sensitive information. + logger.error("Failed to parse the credentials data."); + throw new ConfigurationError("Invalid credentials format."); + } + + const out: Credential[] = []; + for (const e of parsed) { + if (e.url === undefined && e.host === undefined) { + // The proxy needs one of these to work. If both are defined, the url has the precedence. + throw new ConfigurationError( + "Invalid credentials - must specify host or url", + ); + } + + // Filter credentials based on language if specified. `type` is the registry type. + // E.g., "maven_feed" for Java/Kotlin, "nuget_repository" for C#. + if (registryTypeForLanguage && e.type !== registryTypeForLanguage) { + continue; + } + + const isPrintable = (str: string | undefined): boolean => { + return str ? /^[\x20-\x7E]*$/.test(str) : true; + }; + + if ( + !isPrintable(e.type) || + !isPrintable(e.host) || + !isPrintable(e.url) || + !isPrintable(e.username) || + !isPrintable(e.password) || + !isPrintable(e.token) + ) { + throw new ConfigurationError( + "Invalid credentials - fields must contain only printable characters", + ); + } + + out.push({ + type: e.type, + host: e.host, + url: e.url, + username: e.username, + password: e.password, + token: e.token, + }); + } + return out; +} diff --git a/src/tools-features.ts b/src/tools-features.ts index aa70459a96..d14ec0345f 100644 --- a/src/tools-features.ts +++ b/src/tools-features.ts @@ -1,3 +1,5 @@ +import * as semver from "semver"; + import type { VersionInfo } from "./codeql"; export enum ToolsFeature { @@ -26,3 +28,21 @@ export function isSupportedToolsFeature( ): boolean { return !!versionInfo.features && versionInfo.features[feature]; } + +export const SafeArtifactUploadVersion = "2.20.3"; + +/** + * The first version of the CodeQL CLI where artifact upload is safe to use + * for failed runs. This is not really a feature flag, but it is easiest to + * model the behavior as a feature flag. + * + * This was not captured in a tools feature, so we need to use semver. + * + * @param codeQlVersion The version of the CodeQL CLI to check. If not provided, it is assumed to be safe. + * @returns True if artifact upload is safe to use for failed runs or false otherwise. + */ +export function isSafeArtifactUpload(codeQlVersion?: string): boolean { + return !codeQlVersion + ? true + : semver.gte(codeQlVersion, SafeArtifactUploadVersion); +} diff --git a/src/upload-sarif-action-post.ts b/src/upload-sarif-action-post.ts index 3f43b17226..9852b882b9 100644 --- a/src/upload-sarif-action-post.ts +++ b/src/upload-sarif-action-post.ts @@ -30,7 +30,13 @@ async function runWrapper() { return; } await withGroup("Uploading combined SARIF debug artifact", () => - debugArtifacts.uploadCombinedSarifArtifacts(logger, gitHubVersion.type), + debugArtifacts.uploadCombinedSarifArtifacts( + logger, + gitHubVersion.type, + // The codeqlVersion is not applicable for uploading non-codeql sarif. + // We can assume all versions are safe to upload. + undefined, + ), ); } } catch (error) {