diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c340a0d..54f1c98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,28 +2,11 @@ name: ci on: [push, pull_request] jobs: - build-rust: - runs-on: ubuntu-latest - env: - RUST_BACKTRACE: full - # https://github.com/rust-unofficial/patterns/blob/master/anti_patterns/deny-warnings.md - RUSTFLAGS: -D warnings - - steps: - - name: Checkout - uses: actions/checkout@v6 - - name: Install rust - uses: dsherret/rust-toolchain-file@v1 - - name: Clippy - run: | - cargo clippy --all-targets --locked --no-default-features - cargo clippy --all-targets --locked - cargo clippy --all-targets --locked --all-features - - name: Test - run: cargo test --all-features --locked - build-javascript: runs-on: ubuntu-latest + permissions: + contents: read + id-token: write steps: - name: Checkout uses: actions/checkout@v6 @@ -62,7 +45,5 @@ jobs: if: | github.repository == 'denoland/eszip' && startsWith(github.ref, 'refs/tags/') - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - cd npm/ && npm publish + cd npm/ && npm publish --provenance --access public diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 9cf7cb5..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: publish - -on: - push: - tags: - - "*" - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - steps: - - name: Clone repository - uses: actions/checkout@v6 - - uses: rust-lang/crates-io-auth-action@v1 - id: auth - - run: cargo publish - env: - CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d9ec64b..c20d78a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,17 +3,12 @@ name: release on: workflow_dispatch: inputs: - releaseKind: - description: 'Kind of release' - default: 'minor' - type: choice - options: - - patch - - minor + version: + description: 'Version to release (e.g. 0.110.0)' required: true jobs: - rust: + release: name: release runs-on: ubuntu-latest timeout-minutes: 30 @@ -24,11 +19,6 @@ jobs: with: token: ${{ secrets.DENOBOT_PAT }} - - uses: denoland/setup-deno@v2 - with: - deno-version: canary - - uses: dsherret/rust-toolchain-file@v1 - - name: Tag and release env: GITHUB_TOKEN: ${{ secrets.DENOBOT_PAT }} @@ -36,4 +26,5 @@ jobs: run: | git config user.email "denobot@users.noreply.github.com" git config user.name "denobot" - deno run -A jsr:@deno/rust-automation@0.22.1/tasks/publish-release --${{github.event.inputs.releaseKind}} eszip + git tag v${{ github.event.inputs.version }} + git push origin v${{ github.event.inputs.version }} diff --git a/Cargo.lock b/Cargo.lock index df73941..c698102 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "ahash" version = "0.8.12" @@ -31,9 +16,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -45,22 +30,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anstyle" -version = "1.0.11" +name = "anyhow" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] -name = "anyhow" -version = "1.0.99" +name = "ar_archive_writer" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" +dependencies = [ + "object", +] [[package]] name = "ascii" @@ -96,21 +78,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base64" version = "0.21.7" @@ -144,15 +111,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.3" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bitvec" @@ -187,18 +148,18 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" dependencies = [ "allocator-api2", ] [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bytes-str" @@ -232,12 +193,6 @@ dependencies = [ "syn", ] -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - [[package]] name = "castaway" version = "0.2.4" @@ -249,81 +204,30 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.34" +version = "1.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" dependencies = [ + "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "num-traits", "serde", ] -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "clap" -version = "4.5.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" -dependencies = [ - "anstyle", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" - [[package]] name = "compact_str" version = "0.7.1" @@ -337,18 +241,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "console" -version = "0.15.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" -dependencies = [ - "encode_unicode", - "libc", - "once_cell", - "windows-sys 0.59.0", -] - [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -359,22 +251,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "cpufeatures" version = "0.2.17" @@ -384,80 +260,11 @@ dependencies = [ "libc", ] -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "futures", - "is-terminal", - "itertools", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "tokio", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -465,9 +272,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "data-url" @@ -529,9 +336,9 @@ dependencies = [ [[package]] name = "deno_error" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde60bd153886964234c5012d3d9caf788287f28d81fb24a884436904101ef10" +checksum = "3007d3f1ea92ea503324ae15883aac0c2de2b8cf6fead62203ff6a67161007ab" dependencies = [ "deno_error_macro", "libc", @@ -542,9 +349,9 @@ dependencies = [ [[package]] name = "deno_error_macro" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409f265785bd946d3006756955aaf40b0e4deb25752eae6a990afe54a31cfd83" +checksum = "9b565e60a9685cdf312c888665b5f8647ac692a7da7e058a5e2268a466da8eaf" dependencies = [ "proc-macro2", "quote", @@ -586,9 +393,9 @@ dependencies = [ [[package]] name = "deno_lockfile" -version = "0.32.0" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79df4fa29c2e423822bfef1ab5e83093b48481824d5ef7a61c1de1c32c7c302a" +checksum = "3d71c0df1464034be21a9472e7ec8f9a21958418d203fa2c40507fb5cafe799d" dependencies = [ "async-trait", "deno_semver", @@ -646,9 +453,9 @@ dependencies = [ [[package]] name = "deno_semver" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2625b7107cc3f61a462886d5fa77c23e063c1fd15b90e3d5ee2646e9f6178d55" +checksum = "92d46d2fd6959170a6e9f6607a6f79683868fa82ceac56ca520ab014e4fa5b21" dependencies = [ "capacity_builder", "deno_error", @@ -663,9 +470,9 @@ dependencies = [ [[package]] name = "deno_terminal" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23f71c27009e0141dedd315f1dfa3ebb0a6ca4acce7c080fac576ea415a465f6" +checksum = "f3ba8041ae7319b3ca6a64c399df4112badcbbe0868b4517637647614bede4be" dependencies = [ "once_cell", "termcolor", @@ -682,12 +489,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - [[package]] name = "digest" version = "0.10.7" @@ -740,12 +541,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - [[package]] name = "encoding_rs" version = "0.8.35" @@ -761,24 +556,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "eszip" version = "0.109.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91f77b1a4e1402505b12fcc7507a144070e84920a849074a4d3ba5dda17c6fb" dependencies = [ "anyhow", "async-trait", "base64 0.21.7", - "criterion", "deno_ast", "deno_error", "deno_graph", @@ -786,19 +572,12 @@ dependencies = [ "deno_semver", "futures", "hashlink", - "import_map", "indexmap", - "insta", - "jsonc-parser", - "pretty_assertions", - "reqwest", "serde", "serde_json", "sha2", "thiserror", - "tokio", "url", - "xxhash-rust", ] [[package]] @@ -811,7 +590,7 @@ dependencies = [ "deno_graph", "eszip", "futures", - "getrandom 0.2.16", + "getrandom", "import_map", "js-sys", "serde", @@ -823,31 +602,10 @@ dependencies = [ ] [[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fnv" -version = "1.0.7" +name = "find-msvc-tools" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "form_urlencoded" @@ -975,64 +733,17 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "h2" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -1045,9 +756,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "hashlink" @@ -1083,9 +794,9 @@ dependencies = [ [[package]] name = "hstr" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c43c0a9e8fbdb3bb9dc8eee85e1e2ac81605418b4c83b6b7413cbf14d56ca5c" +checksum = "faa57007c3c9dab34df2fa4c1fb52fe9c34ec5a27ed9d8edea53254b50cd7887" dependencies = [ "hashbrown 0.14.5", "new_debug_unreachable", @@ -1095,96 +806,11 @@ dependencies = [ "triomphe", ] -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -1195,9 +821,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -1208,11 +834,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1223,42 +848,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1289,9 +910,9 @@ dependencies = [ [[package]] name = "if_chain" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" +checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" [[package]] name = "import_map" @@ -1312,43 +933,16 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "serde", + "serde_core", ] -[[package]] -name = "insta" -version = "1.43.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371" -dependencies = [ - "console", - "once_cell", - "similar", -] - -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.3", - "cfg-if", - "libc", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - [[package]] name = "is-macro" version = "0.3.7" @@ -1361,31 +955,11 @@ dependencies = [ "syn", ] -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" @@ -1396,80 +970,38 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonc-parser" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7725c320caac8c21d8228c1d055af27a995d371f78cc763073d3e068323641b5" -dependencies = [ - "serde_json", -] - [[package]] name = "libc" -version = "0.2.175" +version = "0.2.181" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", -] +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "monch" @@ -1477,23 +1009,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b52c1b33ff98142aecea13138bd399b68aa7ab5d9546c300988c345004001eea" -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -1541,9 +1056,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -1554,56 +1069,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "oorandom" -version = "11.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - -[[package]] -name = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags 2.9.3", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "outref" version = "0.5.2" @@ -1621,9 +1086,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1631,15 +1096,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -1693,7 +1158,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher 1.0.1", + "siphasher 1.0.2", ] [[package]] @@ -1708,92 +1173,43 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] -[[package]] -name = "pretty_assertions" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" -dependencies = [ - "diff", - "yansi", -] - [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.26" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" +checksum = "3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8" dependencies = [ + "ar_archive_writer", "cc", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "radium" version = "0.7.0" @@ -1815,177 +1231,49 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.3", + "bitflags", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" - -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.16", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustix" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" -dependencies = [ - "bitflags 2.9.3", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", + "regex-syntax", ] [[package]] -name = "rustls" -version = "0.21.12" +name = "regex-automata" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "rustls-pemfile" -version = "1.0.4" +name = "regex-syntax" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] -name = "rustls-webpki" -version = "0.101.7" +name = "rustc-hash" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustversion" @@ -1995,9 +1283,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "ryu-js" @@ -2005,24 +1293,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -2035,39 +1305,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.3", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "seq-macro" version = "0.3.6" @@ -2097,11 +1334,12 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -2126,27 +1364,16 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "indexmap", "itoa", "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -2177,12 +1404,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "similar" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" - [[package]] name = "siphasher" version = "0.3.11" @@ -2191,15 +1412,15 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -2218,26 +1439,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "socket2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "sptr" version = "0.3.2" @@ -2246,15 +1447,15 @@ checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stacker" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" +checksum = "08d74a23609d509411d10e2176dc2a4346e3b4aea2e7b1869f19fdedbc71c013" dependencies = [ "cc", "cfg-if", @@ -2362,7 +1563,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a573a0c72850dec8d4d8085f152d5778af35a2520c3093b242d2d1d50776da7c" dependencies = [ - "bitflags 2.9.3", + "bitflags", "is-macro", "num-bigint", "once_cell", @@ -2417,7 +1618,7 @@ version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e82f7747e052c6ff6e111fa4adeb14e33b46ee6e94fe5ef717601f651db48fc" dependencies = [ - "bitflags 2.9.3", + "bitflags", "either", "num-bigint", "rustc-hash", @@ -2454,7 +1655,7 @@ version = "27.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f1a51af1a92cd4904c073b293e491bbc0918400a45d58227b34c961dd6f52d7" dependencies = [ - "bitflags 2.9.3", + "bitflags", "either", "num-bigint", "phf", @@ -2663,21 +1864,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "synstructure" version = "0.13.2" @@ -2711,46 +1906,12 @@ dependencies = [ "syn", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tempfile" -version = "3.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" -dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -2771,18 +1932,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -2791,97 +1952,28 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "tokio" -version = "1.47.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" -dependencies = [ - "backtrace", - "bytes", - "io-uring", - "libc", - "mio", - "pin-project-lite", - "slab", - "socket2 0.6.0", - "tokio-macros", - "windows-sys 0.59.0", -] - -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.16" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "bytes", - "futures-core", - "futures-sink", "pin-project-lite", - "tokio", ] -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -2890,9 +1982,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -2901,69 +1993,58 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", ] [[package]] name = "triomphe" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" dependencies = [ "serde", "stable_deref_trait", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-id-start" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b" +checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-width" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" - -[[package]] -name = "untrusted" -version = "0.9.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -2978,12 +2059,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -2996,40 +2071,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -3116,38 +2163,20 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "winapi-util" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-targets 0.48.5", + "windows-sys 0.61.2", ] [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -3155,22 +2184,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-link", ] [[package]] @@ -3179,46 +2202,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3231,78 +2236,35 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.3", -] - [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -3313,25 +2275,12 @@ dependencies = [ "tap", ] -[[package]] -name = "xxhash-rust" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" - -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" - [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3339,9 +2288,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -3351,18 +2300,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", @@ -3392,9 +2341,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -3403,9 +2352,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -3414,11 +2363,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7" diff --git a/Cargo.toml b/Cargo.toml index 5b91e2b..cc4adb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,73 +1,34 @@ [package] -name = "eszip" -version = "0.109.0" +name = "eszip_wasm" +version = "0.0.0" authors = ["the Deno authors"] -edition = "2024" -repository = "https://github.com/denoland/eszip" +edition = "2021" description = "A utility that can download JavaScript and TypeScript module graphs and store them locally in a special zip file" license = "MIT" -[workspace] -members = ["lib"] - -[workspace.dependencies] -deno_graph = { version = "0.107.0", default-features = false } -deno_ast = { version = "0.53.0", features = ["transpiling"] } -import_map = "0.24.0" -serde = "1" -deno_error = "0.7.0" +[lib] +name = "eszip_wasm" +path = "src/lib.rs" +crate-type = ["cdylib"] [profile.release] codegen-units = 1 lto = true opt-level = "z" -[lib] -name = "eszip" -path = "src/lib.rs" - -[[example]] -name = "eszip_builder" -path = "src/examples/builder.rs" - -[[example]] -name = "eszip_viewer" -path = "src/examples/viewer.rs" - -[[bench]] -name = "source_hash_function" -harness = false - -[features] -xxhash3 = ["xxhash-rust/xxh3"] -sha256 = ["dep:sha2"] -# backwards compatibility. Disabling sha256 will break compatibility with eszips older than v2.2 -default = ["sha256"] - [dependencies] anyhow = "1" -async-trait = "0.1.68" -base64 = "0.21.0" -deno_ast = { workspace = true } -deno_error.workspace = true -deno_graph = { workspace = true, features = ["swc"] } -deno_npm = { version = "0.43.0" } -deno_semver = "0.9.0" -futures = "0.3.26" -hashlink = "0.8.2" -indexmap = "2" -serde = { workspace = true } -serde_json = "1" -sha2 = { version = "0.10.1", optional = true } -thiserror = "2" -url = "2.2.2" -xxhash-rust = { version = "0.8", optional = true } - -[dev-dependencies] -import_map = { workspace = true } -pretty_assertions = "1" -tokio = { version = "1", features = ["macros", "rt"] } -reqwest = { version = "0.11.23", features = ["rustls-tls"] } -jsonc-parser = { version = "0.23.0", features = ["serde"] } -insta = "1.34.0" -criterion = { version = "0.5", features = ["async_tokio"] } +console_error_panic_hook = "0.1.7" +deno_error = "0.7.0" +deno_graph = { version = "0.107.0", default-features = false } +eszip = "0.109.0" +getrandom = { version = "*", features = ["js"] } +import_map = "0.24.0" +js-sys = "0.3.69" +futures = "0.3.19" +wasm-bindgen = "=0.2.92" +wasm-bindgen-futures = "=0.4.42" +serde = "1" +serde-wasm-bindgen = "0.5.0" +web-sys = { version = "=0.3.69", features = ["ReadableStreamByobReader"] } +sys_traits = { version = "=0.1.17", features = ["real", "wasm"] } diff --git a/README.md b/README.md index f63177c..3339fb9 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,28 @@ # eszip -The eszip format lets you losslessly serialize an ECMAScript module graph -(represented by [`deno_graph::ModuleGraph`][module_graph]) into a single compact -file. +The eszip format lets you losslessly serialize an ECMAScript module graph into a +single compact file. The eszip file format is designed to be compact and streaming capable. This allows for efficient loading of large ECMAScript module graphs. https://eszip-viewer.deno.dev/ is a tool for inspecting eszip files. -[module_graph]: https://docs.rs/deno_graph/latest/deno_graph/struct.ModuleGraph.html +> **Note:** The Rust `eszip` crate source code has been moved to the +> [denoland/deno](https://github.com/denoland/deno) repository. This repository +> contains the JavaScript/WebAssembly bindings that wrap the +> [eszip crate](https://crates.io/crates/eszip). -## Examples - -### Creating an eszip - -```shell -cargo run --example eszip_builder https://deno.land/std/http/file_server.ts file_server.eszip2 -``` - -### Viewing the contents of an eszip - -```shell -cargo run --example eszip_viewer file_server.eszip2 -``` - -### Loading the eszip into V8 - -```shell -cargo run --example eszip_load file_server.eszip2 https://deno.land/std/http/file_server.ts -``` - -## File format +## Development -The file format looks as follows: +Build the Wasm module: ``` -Eszip: -| Magic (8) | Header size (4) | Header (n) | Header hash (32) | Sources size (4) | Sources (n) | SourceMaps size (4) | SourceMaps (n) | - -Header: -( | Specifier size (4) | Specifier (n) | Entry type (1) | Entry (n) | )* - -Entry (redirect): -| Specifier size (4) | Specifier (n) | - -Entry (module): -| Source offset (4) | Source size (4) | SourceMap offset (4) | SourceMap size (4) | Module type (1) | - -Sources: -( | Source (n) | Hash (32) | )* - -SourceMaps: -( | SourceMap (n) | Hash (32) | )* +deno task build ``` -There is one optimization for empty source / source map entries. If both the -offset and size are set to 0, no entry and no hash is present in the data -sections for that module. - -## Development - -When opening a PR make sure to rebuild Wasm by running: +Run tests: ``` -deno task build +deno task test ``` diff --git a/benches/source_hash_function.rs b/benches/source_hash_function.rs deleted file mode 100644 index cf5ad55..0000000 --- a/benches/source_hash_function.rs +++ /dev/null @@ -1,196 +0,0 @@ -use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; -use deno_ast::{EmitOptions, TranspileOptions}; -use deno_graph::{ - BuildOptions, GraphKind, ModuleGraph, ModuleSpecifier, - ast::CapturingModuleAnalyzer, - source::{MemoryLoader, Source}, -}; -use eszip::{EszipV2, v2::Checksum}; -use futures::io::{AllowStdIo, BufReader}; - -#[cfg(feature = "sha256")] -fn into_bytes_sha256(mut eszip: EszipV2) -> Vec { - eszip.set_checksum(Checksum::Sha256); - eszip.into_bytes() -} - -#[cfg(feature = "xxhash3")] -fn into_bytes_xxhash3(mut eszip: EszipV2) -> Vec { - eszip.set_checksum(Checksum::XxHash3); - eszip.into_bytes() -} - -fn into_bytes_no_checksum(mut eszip: EszipV2) -> Vec { - eszip.set_checksum(Checksum::NoChecksum); - eszip.into_bytes() -} - -async fn parse(bytes: &[u8]) -> EszipV2 { - let (eszip, fut) = EszipV2::parse(BufReader::new(AllowStdIo::new(bytes))) - .await - .unwrap(); - fut.await.unwrap(); - eszip -} - -fn bench_into_bytes(c: &mut Criterion) { - let mut group = c.benchmark_group("into_bytes()"); - group.sample_size(10); - for mb in (1..200).step_by(20) { - group.throughput(criterion::Throughput::Bytes((mb as u64) << 20)); - #[cfg(feature = "sha256")] - group.bench_with_input( - BenchmarkId::new("SHA256", format!("{mb}MB")), - &mb, - |b, mb| { - b.iter_batched( - || { - let rt = tokio::runtime::Builder::new_current_thread() - .build() - .unwrap(); - rt.block_on(build_eszip(*mb)) - }, - into_bytes_sha256, - criterion::BatchSize::SmallInput, - ) - }, - ); - #[cfg(feature = "xxhash3")] - group.bench_with_input( - BenchmarkId::new("XXHASH3", format!("{mb}MB")), - &mb, - |b, mb| { - b.iter_batched( - || { - let rt = tokio::runtime::Builder::new_current_thread() - .build() - .unwrap(); - rt.block_on(build_eszip(*mb)) - }, - into_bytes_xxhash3, - criterion::BatchSize::SmallInput, - ) - }, - ); - group.bench_with_input( - BenchmarkId::new("NO-CHECkSUM", format!("{mb}MB")), - &mb, - |b, mb| { - b.iter_batched( - || { - let rt = tokio::runtime::Builder::new_current_thread() - .build() - .unwrap(); - rt.block_on(build_eszip(*mb)) - }, - into_bytes_no_checksum, - criterion::BatchSize::SmallInput, - ) - }, - ); - } - group.finish(); -} - -fn bench_parse(c: &mut Criterion) { - let mut group = c.benchmark_group("parse()"); - group.sample_size(10); - for mb in (1..200).step_by(20) { - group.throughput(criterion::Throughput::Bytes((mb as u64) << 20)); - let rt = tokio::runtime::Builder::new_current_thread() - .build() - .unwrap(); - - #[cfg(feature = "sha256")] - { - let mut eszip = rt.block_on(build_eszip(mb)); - eszip.set_checksum(Checksum::Sha256); - let bytes = eszip.into_bytes(); - group.bench_with_input( - BenchmarkId::new("SHA256", format!("{mb}MB")), - &bytes, - |b, bytes| b.to_async(&rt).iter(|| parse(bytes)), - ); - } - #[cfg(feature = "xxhash3")] - { - let mut eszip = rt.block_on(build_eszip(mb)); - eszip.set_checksum(Checksum::XxHash3); - let bytes = eszip.into_bytes(); - group.bench_with_input( - BenchmarkId::new("XXHASH3", format!("{mb}MB")), - &bytes, - |b, bytes| b.to_async(&rt).iter(|| parse(bytes)), - ); - } - let mut eszip = rt.block_on(build_eszip(mb)); - eszip.set_checksum(Checksum::NoChecksum); - let bytes = eszip.into_bytes(); - group.bench_with_input( - BenchmarkId::new("NO-CHECKSUM", format!("{mb}MB")), - &bytes, - |b, bytes| b.to_async(&rt).iter(|| parse(bytes)), - ); - } - group.finish(); -} - -criterion_group!(benches, bench_into_bytes, bench_parse); -criterion_main!(benches); - -async fn build_eszip(mb: usize) -> EszipV2 { - let roots = vec![ModuleSpecifier::parse("file:///module1.js").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let mut sources = vec![( - String::from("file:///module1.js"), - Source::Module { - specifier: String::from("file:///module1.js"), - maybe_headers: None, - content: (2..=mb) - .map(|x| format!(r#"import "./module{x}.js";"#)) - .chain([build_comment_module(1)]) - .collect::>() - .join("\n"), - }, - )]; - for x in 2..=mb { - let specifier = format!("file:///module{x}.js"); - sources.push(( - specifier.clone(), - Source::Module { - specifier, - maybe_headers: None, - content: build_comment_module(1), - }, - )) - } - let loader = MemoryLoader::new(sources, Vec::new()); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - EszipV2::from_graph(eszip::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap() -} - -fn build_comment_module(mb: usize) -> String { - format!("// {}", "a".repeat(mb << 20)) -} diff --git a/deno.json b/deno.json index 8e44222..915f313 100644 --- a/deno.json +++ b/deno.json @@ -1,9 +1,9 @@ { "tasks": { - "build": "cp LICENSE js/LICENSE && RUSTFLAGS=--cfg=web_sys_unstable_apis deno run -A jsr:@deno/wasmbuild@0.17.1 --all-features --out js", + "build": "cp LICENSE js/LICENSE && RUSTFLAGS=--cfg=web_sys_unstable_apis deno run -A jsr:@deno/wasmbuild@0.17.1 --out js", "node": "deno run -A ./build_npm.ts 0.0.0", "test": "deno test -A js/", "fmt": "deno fmt && cargo fmt --all" }, - "exclude": ["./npm", "./src/testdata/", "./target"] + "exclude": ["./npm", "./target"] } diff --git a/lib/Cargo.toml b/lib/Cargo.toml deleted file mode 100644 index d8c2851..0000000 --- a/lib/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "eszip_wasm" -version = "0.0.0" -authors = ["the Deno authors"] -edition = "2021" -description = "A utility that can download JavaScript and TypeScript module graphs and store them locally in a special zip file" -license = "MIT" - -[lib] -name = "eszip_wasm" -path = "lib.rs" -crate-type = ["cdylib"] - -[dependencies] -anyhow = "1" -console_error_panic_hook = "0.1.7" -deno_graph = { workspace = true } -deno_error.workspace = true -eszip = { path = "../" } -getrandom = { version = "*", features = ["js"] } -import_map = { workspace = true } -js-sys = { version = "0.3.69" } -futures = "0.3.19" -wasm-bindgen = { version = "=0.2.92" } -wasm-bindgen-futures = { version = "=0.4.42" } -serde = { workspace = true } -serde-wasm-bindgen = "0.5.0" -web-sys = { version = "=0.3.69", features = ["ReadableStreamByobReader"] } -sys_traits = { version = "0.1.12", features = ["real", "wasm"] } diff --git a/lib/lib.rs b/lib/lib.rs deleted file mode 100644 index ce12124..0000000 --- a/lib/lib.rs +++ /dev/null @@ -1,449 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -#![deny(clippy::print_stderr)] -#![deny(clippy::print_stdout)] - -use deno_error::JsErrorBox; -use deno_graph::source::load_data_url; -use deno_graph::source::CacheInfo; -use deno_graph::source::LoadFuture; -use deno_graph::source::LoadOptions; -use deno_graph::source::Loader; -use deno_graph::source::ResolveError; -use deno_graph::source::Resolver; -use deno_graph::BuildOptions; -use deno_graph::GraphKind; -use deno_graph::ModuleGraph; -use deno_graph::ModuleSpecifier; -use eszip::v2::Url; -use eszip::ModuleKind; -use futures::io::AsyncRead; -use futures::io::BufReader; -use import_map::ImportMap; -use js_sys::Promise; -use js_sys::TypeError; -use js_sys::Uint8Array; -use serde::Serialize; -use std::cell::RefCell; -use std::future::Future; -use std::io::Error; -use std::io::ErrorKind; -use std::pin::Pin; -use std::rc::Rc; -use std::sync::Arc; -use std::task::Context; -use std::task::Poll; -use wasm_bindgen::prelude::*; -use wasm_bindgen::JsCast; -use wasm_bindgen_futures::JsFuture; -use web_sys::ReadableStreamByobReader; - -/// A `Stream` holds a Byob reader and the -/// future of the current `reader.read` operation. -struct Stream { - inner: Option, - fut: Option, -} - -impl Stream { - fn new(inner: ReadableStreamByobReader) -> Self { - Self { - inner: Some(inner), - fut: None, - } - } -} - -#[wasm_bindgen] -extern "C" { - /// Result of a read on BYOB reader. - /// { value: Uint8Array, done: boolean } - pub type ReadResult; - #[wasm_bindgen(method, getter, js_name = done)] - pub fn is_done(this: &ReadResult) -> bool; - - #[wasm_bindgen(method, getter, js_name = value)] - pub fn value(this: &ReadResult) -> Option; -} - -/// A `ParserStream` is a wrapper around -/// Byob stream that also supports reading -/// through in-memory buffers. -/// -/// We need this because `#[wasm_bindgen]` -/// structs cannot have type parameters. -enum ParserStream { - Byob(Stream), - Buffer(Vec), -} - -impl AsyncRead for ParserStream { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &mut [u8], - ) -> Poll> { - match *self { - ParserStream::Byob(ref mut stream) => { - // If we have a pending future, poll it. - // otherwise, schedule a new one. - let fut = match stream.fut.as_mut() { - Some(fut) => fut, - None => { - let length = buf.len(); - let buffer = Uint8Array::new_with_length(length as u32); - match &stream.inner { - Some(reader) => { - let fut = - JsFuture::from(reader.read_with_array_buffer_view(&buffer)); - stream.fut.insert(fut) - } - None => return Poll::Ready(Ok(0)), - } - } - }; - let result = match Pin::new(fut).poll(cx) { - Poll::Ready(result) => result, - Poll::Pending => return Poll::Pending, - }; - // Clear slot for next `read()`. - stream.fut = None; - - match result { - Ok(result) => { - let result = result.unchecked_into::(); - match result.is_done() { - true => { - // Drop the readable stream. - stream.inner = None; - Poll::Ready(Ok(0)) - } - false => { - let value = result.value().unwrap_throw(); - let length = value.byte_length() as usize; - - value.copy_to(buf); - - Poll::Ready(Ok(length)) - } - } - } - Err(e) => Poll::Ready(Err(Error::new( - ErrorKind::Other, - js_sys::Object::try_from(&e) - .map(|e| e.to_string().as_string().unwrap_throw()) - .unwrap_or("Unknown error".to_string()), - ))), - } - } - ParserStream::Buffer(ref mut buffer) => { - // Put the requested bytes into the buffer and - // assign the remaining bytes back into the sink. - let amt = std::cmp::min(buffer.len(), buf.len()); - let (a, b) = buffer.split_at(amt); - buf[..amt].copy_from_slice(a); - *buffer = b.to_vec(); - Poll::Ready(Ok(amt)) - } - } - } -} - -type LoaderFut = - Pin, eszip::ParseError>>>>; -type ParseResult = (eszip::EszipV2, LoaderFut); - -#[wasm_bindgen] -pub struct Parser { - parser: Rc>>>, -} - -#[wasm_bindgen] -impl Parser { - #[wasm_bindgen(constructor)] - pub fn new() -> Self { - std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - Self { - parser: Rc::new(RefCell::new(None)), - } - } - - /// Parse from a BYOB readable stream. - pub fn parse(&self, stream: ReadableStreamByobReader) -> Promise { - let reader = BufReader::new(ParserStream::Byob(Stream::new(stream))); - self.parse_reader(reader) - } - - /// Parse from an in-memory buffer. - #[wasm_bindgen(js_name = parseBytes)] - pub fn parse_bytes(&self, buffer: Vec) -> Promise { - let reader = BufReader::new(ParserStream::Buffer(buffer)); - self.parse_reader(reader) - } - - fn parse_reader(&self, reader: BufReader) -> Promise { - let parser = Rc::clone(&self.parser); - - wasm_bindgen_futures::future_to_promise(async move { - let (eszip, loader) = eszip::EszipV2::parse(reader).await.unwrap(); - let specifiers = eszip.specifiers(); - parser.borrow_mut().replace((eszip, Box::pin(loader))); - Ok( - specifiers - .iter() - .map(JsValue::from) - .collect::() - .into(), - ) - }) - } - - /// Load module sources. - pub fn load(&mut self) -> Promise { - let parser = Rc::clone(&self.parser); - - wasm_bindgen_futures::future_to_promise(async move { - let mut p = parser.borrow_mut(); - let (_, loader) = p.as_mut().unwrap_throw(); - loader.await.unwrap(); - Ok(JsValue::UNDEFINED) - }) - } - - /// Get a module source. - #[wasm_bindgen(js_name = getModuleSource)] - pub fn get_module_source(&self, specifier: String) -> Promise { - let parser = Rc::clone(&self.parser); - - wasm_bindgen_futures::future_to_promise(async move { - let p = parser.borrow(); - let (eszip, _) = p.as_ref().unwrap(); - let module = eszip - .get_module(&specifier) - .or_else(|| eszip.get_import_map(&specifier)) - .ok_or(TypeError::new(&format!("module '{}' not found", specifier)))?; - - // Drop the borrow for the loader - // to mutably borrow. - drop(p); - let source = module.source().await.ok_or(TypeError::new(&format!( - "source for '{}' already taken", - specifier - )))?; - let source = std::str::from_utf8(&source).unwrap(); - Ok(source.to_string().into()) - }) - } - - /// Get a module sourcemap. - #[wasm_bindgen(js_name = getModuleSourceMap)] - pub fn get_module_source_map(&self, specifier: String) -> Promise { - let parser = Rc::clone(&self.parser); - - wasm_bindgen_futures::future_to_promise(async move { - let p = parser.borrow(); - let (eszip, _) = p.as_ref().unwrap(); - let module = eszip - .get_module(&specifier) - .or_else(|| eszip.get_import_map(&specifier)) - .ok_or(TypeError::new(&format!("module '{}' not found", specifier)))?; - - // Drop the borrow for the loader - // to mutably borrow. - drop(p); - match module.source_map().await { - Some(source_map) => { - let source_map = std::str::from_utf8(&source_map).unwrap(); - Ok(source_map.to_string().into()) - } - None => Ok(JsValue::NULL), - } - }) - } -} - -/// Serialize a module graph into eszip. -#[wasm_bindgen(js_name = build)] -pub async fn build_eszip( - roots: JsValue, - loader: js_sys::Function, - import_map_url: JsValue, -) -> Result { - std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - let roots: Vec = - serde_wasm_bindgen::from_value(roots) - .map_err(|e| js_sys::Error::new(&e.to_string()))?; - let loader = GraphLoader(loader); - let import_map_url: Option = - serde_wasm_bindgen::from_value(import_map_url) - .map_err(|e| js_sys::Error::new(&e.to_string()))?; - let (maybe_import_map, maybe_import_map_data) = if let Some(import_map_url) = - import_map_url - { - let resp = deno_graph::source::Loader::load( - &loader, - &import_map_url, - deno_graph::source::LoadOptions { - in_dynamic_branch: false, - was_dynamic_root: false, - cache_setting: deno_graph::source::CacheSetting::Use, - maybe_checksum: None, - }, - ) - .await - .map_err(|e| js_sys::Error::new(&e.to_string()))? - .ok_or_else(|| { - js_sys::Error::new(&format!("import map not found at '{import_map_url}'")) - })?; - match resp { - deno_graph::source::LoadResponse::Module { - specifier, content, .. - } => { - let import_map = import_map::parse_from_json_with_options( - specifier.clone(), - &String::from_utf8(content.to_vec()).unwrap(), - import_map::ImportMapOptions { - address_hook: None, - // always do this for simplicity - expand_imports: true, - }, - ) - .unwrap(); - (Some(import_map.import_map), Some((specifier, content))) - } - _ => unimplemented!(), - } - } else { - (None, None) - }; - let resolver = GraphResolver(maybe_import_map); - let analyzer = deno_graph::ast::CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - resolver: Some(&resolver), - module_analyzer: &analyzer, - file_system: &sys_traits::impls::RealSys, - ..Default::default() - }, - ) - .await; - graph - .valid() - .map_err(|e| js_sys::Error::new(&e.to_string()))?; - let mut eszip = eszip::EszipV2::from_graph(eszip::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: Default::default(), - emit_options: Default::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .map_err(|e| js_sys::Error::new(&e.to_string()))?; - if let Some((import_map_specifier, import_map_content)) = - maybe_import_map_data - { - eszip.add_import_map( - ModuleKind::Json, - import_map_specifier.to_string(), - Arc::from(import_map_content), - ) - } - Ok(Uint8Array::from(eszip.into_bytes().as_slice())) -} - -// Taken from deno_graph -// https://github.com/denoland/deno_graph/blob/main/src/js_graph.rs#L43 -pub struct GraphLoader(js_sys::Function); - -impl Loader for GraphLoader { - fn get_cache_info(&self, _: &ModuleSpecifier) -> Option { - None - } - - fn load( - &self, - specifier: &ModuleSpecifier, - options: LoadOptions, - ) -> LoadFuture { - #[derive(Serialize)] - #[serde(rename_all = "camelCase")] - struct JsLoadOptions { - pub is_dynamic: bool, - pub cache_setting: &'static str, - pub checksum: Option, - } - - if specifier.scheme() == "data" { - Box::pin(std::future::ready(load_data_url(specifier).map_err( - |err| { - deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::from_err( - err, - ))) - }, - ))) - } else { - let specifier = specifier.clone(); - let result = self.0.call2( - &JsValue::null(), - &JsValue::from(specifier.to_string()), - &serde_wasm_bindgen::to_value(&JsLoadOptions { - is_dynamic: options.in_dynamic_branch, - cache_setting: options.cache_setting.as_js_str(), - checksum: options.maybe_checksum.map(|c| c.into_string()), - }) - .unwrap(), - ); - Box::pin(async move { - let response = match result { - Ok(result) => { - wasm_bindgen_futures::JsFuture::from(js_sys::Promise::resolve( - &result, - )) - .await - } - Err(err) => Err(err), - }; - response - .map(|value| serde_wasm_bindgen::from_value(value).unwrap()) - .map_err(|err| { - let err_str = err - .as_string() - .unwrap_or_else(|| "an error occured during loading".to_string()); - deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::generic( - err_str, - ))) - }) - }) - } - } -} - -#[derive(Debug)] -pub struct GraphResolver(Option); - -impl Resolver for GraphResolver { - fn resolve( - &self, - specifier: &str, - referrer_range: &deno_graph::Range, - _kind: deno_graph::source::ResolutionKind, - ) -> Result { - if let Some(import_map) = &self.0 { - import_map - .resolve(specifier, &referrer_range.specifier) - .map_err(ResolveError::from_err) - } else { - Ok(deno_graph::resolve_import( - specifier, - &referrer_range.specifier, - )?) - } - } -} diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index 2444867..0000000 --- a/src/error.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum ParseError { - #[error("invalid eszip v1: {0}")] - InvalidV1Json(serde_json::Error), - #[error("invalid eszip v1 version: got {0}, expected 1")] - InvalidV1Version(u32), - #[error("invalid eszip v2")] - InvalidV2, - #[error("invalid eszip v2 header hash")] - InvalidV2HeaderHash, - #[error("invalid specifier in eszip v2 header at offset {0}")] - InvalidV2Specifier(usize), - #[error("invalid entry kind {0} in eszip v2 header at offset {0}")] - InvalidV2EntryKind(u8, usize), - #[error("invalid module kind {0} in eszip v2 header at offset {0}")] - InvalidV2ModuleKind(u8, usize), - #[error("invalid eszip v2 header: {0}")] - InvalidV2Header(&'static str), - #[error("invalid eszip v2 source offset ({0})")] - InvalidV2SourceOffset(usize), - #[error("invalid eszip v2 source hash (specifier {0})")] - InvalidV2SourceHash(String), - #[error("invalid eszip v2.1 npm snapshot hash")] - InvalidV2NpmSnapshotHash, - #[error("invalid eszip v2.1 npm package at index {0}. {1:#}")] - InvalidV2NpmPackageOffset(usize, std::io::Error), - #[error("invalid eszip v2.1 npm package '{0}'. {1:#}")] - InvalidV2NpmPackage(String, anyhow::Error), - #[error("invalid eszip v2.1 npm req '{0}'. {1:#}")] - InvalidV2NpmPackageReq(String, anyhow::Error), - #[error("invalid eszip v2.2 options header")] - InvalidV22OptionsHeader(String), - #[error("invalid eszip v2.2 options header hash")] - InvalidV22OptionsHeaderHash, - - #[error(transparent)] - Io(#[from] std::io::Error), -} diff --git a/src/examples/builder.rs b/src/examples/builder.rs deleted file mode 100644 index 90779de..0000000 --- a/src/examples/builder.rs +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::collections::HashMap; -use std::sync::Arc; - -use deno_ast::EmitOptions; -use deno_ast::TranspileOptions; -use deno_error::JsErrorBox; -use deno_graph::BuildOptions; -use deno_graph::GraphKind; -use deno_graph::ModuleGraph; -use deno_graph::ast::CapturingModuleAnalyzer; -use deno_graph::source::CacheSetting; -use deno_graph::source::ResolveError; -use import_map::ImportMap; -use reqwest::StatusCode; -use url::Url; - -#[tokio::main(flavor = "current_thread")] -async fn main() { - let args = std::env::args().collect::>(); - let url = args.get(1).unwrap(); - let url = Url::parse(url).unwrap(); - let out = args.get(2).unwrap(); - let maybe_import_map = args.get(3).map(|url| Url::parse(url).unwrap()); - - let loader = Loader; - let (maybe_import_map, maybe_import_map_data) = - if let Some(import_map_url) = maybe_import_map { - let resp = deno_graph::source::Loader::load( - &loader, - &import_map_url, - deno_graph::source::LoadOptions { - in_dynamic_branch: false, - was_dynamic_root: false, - cache_setting: CacheSetting::Use, - maybe_checksum: None, - }, - ) - .await - .unwrap() - .unwrap(); - match resp { - deno_graph::source::LoadResponse::Module { - specifier, content, .. - } => { - let content = String::from_utf8(content.to_vec()).unwrap(); - let import_map = - import_map::parse_from_json(specifier.clone(), &content).unwrap(); - (Some(import_map.import_map), Some((specifier, content))) - } - _ => unimplemented!(), - } - } else { - (None, None) - }; - - let analyzer = CapturingModuleAnalyzer::default(); - - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - graph - .build( - vec![url], - Vec::new(), - &loader, - BuildOptions { - resolver: Some(&Resolver(maybe_import_map)), - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - - graph.valid().unwrap(); - - let mut eszip = eszip::EszipV2::from_graph(eszip::FromGraphOptions { - graph, - parser: analyzer.as_capturing_parser(), - module_kind_resolver: Default::default(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - if let Some((import_map_specifier, import_map_content)) = - maybe_import_map_data - { - eszip.add_import_map( - eszip::ModuleKind::Json, - import_map_specifier.to_string(), - Arc::from(import_map_content.into_bytes()), - ) - } - for specifier in eszip.specifiers() { - println!("source: {specifier}") - } - - let bytes = eszip.into_bytes(); - - std::fs::write(out, bytes).unwrap(); -} - -#[derive(Debug)] -struct Resolver(Option); - -impl deno_graph::source::Resolver for Resolver { - fn resolve( - &self, - specifier: &str, - referrer_range: &deno_graph::Range, - _kind: deno_graph::source::ResolutionKind, - ) -> Result { - if let Some(import_map) = &self.0 { - import_map - .resolve(specifier, &referrer_range.specifier) - .map_err(ResolveError::from_err) - } else { - Ok(deno_graph::resolve_import( - specifier, - &referrer_range.specifier, - )?) - } - } -} - -struct Loader; - -impl deno_graph::source::Loader for Loader { - fn load( - &self, - specifier: &deno_graph::ModuleSpecifier, - _options: deno_graph::source::LoadOptions, - ) -> deno_graph::source::LoadFuture { - let specifier = specifier.clone(); - - Box::pin(async move { - match specifier.scheme() { - "data" => { - deno_graph::source::load_data_url(&specifier).map_err(|err| { - deno_graph::source::LoadError::Other(Arc::new( - JsErrorBox::from_err(err), - )) - }) - } - "file" => { - let path = std::fs::canonicalize(specifier.to_file_path().unwrap()) - .map_err(|err| { - deno_graph::source::LoadError::Other(Arc::new( - JsErrorBox::from_err(err), - )) - })?; - let content = std::fs::read(&path).map_err(|err| { - deno_graph::source::LoadError::Other(Arc::new( - JsErrorBox::from_err(err), - )) - })?; - Ok(Some(deno_graph::source::LoadResponse::Module { - specifier: Url::from_file_path(&path).unwrap(), - maybe_headers: None, - mtime: None, - content: Arc::from(content), - })) - } - "http" | "https" => { - let resp = reqwest::get(specifier.as_str()).await.map_err(|err| { - deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::generic( - err.to_string(), - ))) - })?; - if resp.status() == StatusCode::NOT_FOUND { - Ok(None) - } else { - let resp = resp.error_for_status().map_err(|err| { - deno_graph::source::LoadError::Other(Arc::new( - JsErrorBox::generic(err.to_string()), - )) - })?; - let mut headers = HashMap::new(); - for key in resp.headers().keys() { - let key_str = key.to_string(); - let values = resp.headers().get_all(key); - let values_str = values - .iter() - .filter_map(|e| e.to_str().ok()) - .collect::>() - .join(","); - headers.insert(key_str, values_str); - } - let url = resp.url().clone(); - let content = resp.bytes().await.map_err(|err| { - deno_graph::source::LoadError::Other(Arc::new( - JsErrorBox::generic(err.to_string()), - )) - })?; - Ok(Some(deno_graph::source::LoadResponse::Module { - specifier: url, - mtime: None, - maybe_headers: Some(headers), - content: Arc::from(content.as_ref()), - })) - } - } - _ => { - let err: Arc = - Arc::new(JsErrorBox::generic(format!( - "unsupported scheme: {}", - specifier.scheme() - ))); - Err(deno_graph::source::LoadError::Other(err)) - } - } - }) - } -} diff --git a/src/examples/viewer.rs b/src/examples/viewer.rs deleted file mode 100644 index 1bf0be7..0000000 --- a/src/examples/viewer.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use futures::io::AllowStdIo; -use futures::io::BufReader; -use std::env; -use std::fs; -use std::path::PathBuf; - -#[tokio::main(flavor = "current_thread")] -async fn main() { - let args: Vec = env::args().collect(); - let (eszip_path, output_dir) = match parse_args(args) { - Ok(result) => result, - Err(err) => { - eprintln!("Error: {}", err); - print_help(); - return; - } - }; - - let file = std::fs::File::open(&eszip_path).unwrap(); - let bufreader = BufReader::new(AllowStdIo::new(file)); - let (eszip, loader) = eszip::EszipV2::parse(bufreader).await.unwrap(); - - let fut = async move { - for (specifier, module) in eszip { - if module.specifier == specifier { - // skip extracting data specifiers. - if specifier.starts_with("data:") { - continue; - } - let source = module.source().await.expect("source already taken"); - let source = std::str::from_utf8(&source).unwrap(); - - if let Some(ref output_dir) = output_dir { - let specifier = specifier - .trim_start_matches("file:///") - .trim_start_matches("http://") - .trim_start_matches("https://"); - let file_path = output_dir.join( - PathBuf::from(&specifier) - .strip_prefix("/") - .unwrap_or(&PathBuf::from(&specifier)), - ); - if let Some(parent) = file_path.parent() { - fs::create_dir_all(parent).expect("Failed to create directory"); - } - fs::write(&file_path, source).expect("Failed to write file"); - println!("Extracted {}", file_path.display()); - } else { - println!("Specifier: {specifier}",); - println!("Kind: {kind:?}", kind = module.kind); - println!("---"); - println!("{source}"); - - let source_map = module.source_map().await; - if let Some(source_map) = source_map { - let source_map = std::str::from_utf8(&source_map).unwrap(); - println!("---"); - println!("{source_map}"); - } - - println!("============"); - } - } - } - - Ok(()) - }; - - tokio::try_join!(loader, fut).unwrap(); -} - -fn print_help() { - println!("Usage:"); - println!(" viewer "); - println!(" viewer --output "); - println!(" viewer -o "); -} - -fn parse_args(args: Vec) -> Result<(PathBuf, Option), String> { - let mut output_dir = None; - let mut eszip_path = None; - let mut args_iter = args.into_iter().skip(1); - while let Some(arg) = args_iter.next() { - match arg.as_str() { - "--output" | "-o" => { - output_dir = Some(PathBuf::from( - args_iter.next().ok_or("Missing output directory")?, - )); - } - _ if eszip_path.is_none() => { - eszip_path = Some(PathBuf::from(arg)); - } - _ => return Err(format!("Unknown argument: {}", arg)), - } - } - let eszip_path = eszip_path.ok_or("Missing eszip path")?; - Ok((eszip_path, output_dir)) -} diff --git a/src/lib.rs b/src/lib.rs index 9a90626..d0dc951 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,384 +2,447 @@ #![deny(clippy::print_stderr)] #![deny(clippy::print_stdout)] -#![deny(clippy::unused_async)] -mod error; -pub mod v1; -pub mod v2; - -use std::sync::Arc; - -use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; -use futures::future::BoxFuture; -use futures::future::LocalBoxFuture; -use futures::io::AsyncBufReadExt; -use futures::io::AsyncReadExt; -use serde::Deserialize; +use deno_error::JsErrorBox; +use deno_graph::source::load_data_url; +use deno_graph::source::CacheInfo; +use deno_graph::source::LoadFuture; +use deno_graph::source::LoadOptions; +use deno_graph::source::Loader; +use deno_graph::source::ResolveError; +use deno_graph::source::Resolver; +use deno_graph::BuildOptions; +use deno_graph::GraphKind; +use deno_graph::ModuleGraph; +use deno_graph::ModuleSpecifier; +use eszip::ModuleKind; +use futures::io::AsyncRead; +use futures::io::BufReader; +use import_map::ImportMap; +use js_sys::Promise; +use js_sys::TypeError; +use js_sys::Uint8Array; use serde::Serialize; -use v2::EszipV2Modules; -use v2::EszipVersion; - -pub use crate::error::ParseError; -pub use crate::v1::EszipV1; -pub use crate::v2::EszipRelativeFileBaseUrl; -pub use crate::v2::EszipV2; -pub use crate::v2::FromGraphOptions; - -pub use deno_ast; -pub use deno_graph; - -pub enum Eszip { - V1(EszipV1), - V2(EszipV2), +use std::cell::RefCell; +use std::future::Future; +use std::io::Error; +use std::io::ErrorKind; +use std::pin::Pin; +use std::rc::Rc; +use std::sync::Arc; +use std::task::Context; +use std::task::Poll; +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; +use wasm_bindgen_futures::JsFuture; +use web_sys::ReadableStreamByobReader; + +/// A `Stream` holds a Byob reader and the +/// future of the current `reader.read` operation. +struct Stream { + inner: Option, + fut: Option, } -type EszipParserOutput = Result, ParseError>; - -/// This future needs to polled to parse the eszip file. -type EszipParserFuture = BoxFuture<'static, EszipParserOutput>; -/// This future needs to polled to parse the eszip file. -type EszipParserLocalFuture = LocalBoxFuture<'static, EszipParserOutput>; - -impl Eszip { - /// Parse a byte stream into an Eszip. This function completes when the header - /// is fully received. This does not mean that the entire file is fully - /// received or parsed yet. To finish parsing, the future returned by this - /// function in the second tuple slot needs to be polled. - pub async fn parse( - reader: R, - ) -> Result<(Eszip, EszipParserFuture), ParseError> { - let mut reader = futures::io::BufReader::new(reader); - let mut magic = [0; 8]; - reader.read_exact(&mut magic).await?; - if let Some(version) = EszipVersion::from_magic(&magic) { - let (eszip, fut) = EszipV2::parse_with_version(version, reader).await?; - Ok((Eszip::V2(eszip), Box::pin(fut))) - } else { - let mut buffer = Vec::new(); - let mut reader_w_magic = magic.chain(&mut reader); - reader_w_magic.read_to_end(&mut buffer).await?; - let eszip = EszipV1::parse(&buffer)?; - let fut = async move { Ok::<_, ParseError>(reader) }; - Ok((Eszip::V1(eszip), Box::pin(fut))) - } - } - - /// Parse a byte stream into an Eszip. This function completes when the header - /// is fully received. This does not mean that the entire file is fully - /// received or parsed yet. To finish parsing, the future returned by this - /// function in the second tuple slot needs to be polled. - /// - /// As opposed to [`Eszip::parse`], this method accepts `!Send` reader. The - /// returned future does not implement `Send` either. - pub async fn parse_local( - reader: R, - ) -> Result<(Eszip, EszipParserLocalFuture), ParseError> { - let mut reader = futures::io::BufReader::new(reader); - reader.fill_buf().await?; - let buffer = reader.buffer(); - if EszipV2::has_magic(buffer) { - let (eszip, fut) = EszipV2::parse(reader).await?; - Ok((Eszip::V2(eszip), Box::pin(fut))) - } else { - let mut buffer = Vec::new(); - reader.read_to_end(&mut buffer).await?; - let eszip = EszipV1::parse(&buffer)?; - let fut = async move { Ok::<_, ParseError>(reader) }; - Ok((Eszip::V1(eszip), Box::pin(fut))) - } - } - - /// Get the module metadata for a given module specifier. This function will - /// follow redirects. The returned module has functions that can be used to - /// obtain the module source and source map. The module returned from this - /// function is guaranteed to be a valid module, which can be loaded into v8. - /// - /// Note that this function should be used to obtain a module; if you wish to - /// get an import map, use [`get_import_map`](Self::get_import_map) instead. - pub fn get_module(&self, specifier: &str) -> Option { - match self { - Eszip::V1(eszip) => eszip.get_module(specifier), - Eszip::V2(eszip) => eszip.get_module(specifier), +impl Stream { + fn new(inner: ReadableStreamByobReader) -> Self { + Self { + inner: Some(inner), + fut: None, } } +} - /// Get the import map for a given specifier. - /// - /// Note that this function should be used to obtain an import map; the returned - /// "Module" is not necessarily a valid module that can be loaded into v8 (in - /// other words, JSONC may be returned). If you wish to get a valid module, - /// use [`get_module`](Self::get_module) instead. - pub fn get_import_map(&self, specifier: &str) -> Option { - match self { - Eszip::V1(eszip) => eszip.get_import_map(specifier), - Eszip::V2(eszip) => eszip.get_import_map(specifier), - } - } +#[wasm_bindgen] +extern "C" { + /// Result of a read on BYOB reader. + /// { value: Uint8Array, done: boolean } + pub type ReadResult; + #[wasm_bindgen(method, getter, js_name = done)] + pub fn is_done(this: &ReadResult) -> bool; - /// Takes the npm snapshot out of the eszip. - pub fn take_npm_snapshot( - &mut self, - ) -> Option { - match self { - Eszip::V1(_) => None, - Eszip::V2(eszip) => eszip.take_npm_snapshot(), - } - } + #[wasm_bindgen(method, getter, js_name = value)] + pub fn value(this: &ReadResult) -> Option; } -/// Get an iterator over all the modules (including an import map, if any) in -/// this eszip archive. +/// A `ParserStream` is a wrapper around +/// Byob stream that also supports reading +/// through in-memory buffers. /// -/// Note that the iterator will iterate over the specifiers' "snapshot" of the -/// archive. If a new module is added to the archive after the iterator is -/// created via `into_iter()`, that module will not be iterated over. -impl IntoIterator for Eszip { - type Item = (String, Module); - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - match self { - Eszip::V1(eszip) => eszip.into_iter(), - Eszip::V2(eszip) => eszip.into_iter(), +/// We need this because `#[wasm_bindgen]` +/// structs cannot have type parameters. +enum ParserStream { + Byob(Stream), + Buffer(Vec), +} + +impl AsyncRead for ParserStream { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + match *self { + ParserStream::Byob(ref mut stream) => { + // If we have a pending future, poll it. + // otherwise, schedule a new one. + let fut = match stream.fut.as_mut() { + Some(fut) => fut, + None => { + let length = buf.len(); + let buffer = Uint8Array::new_with_length(length as u32); + match &stream.inner { + Some(reader) => { + let fut = + JsFuture::from(reader.read_with_array_buffer_view(&buffer)); + stream.fut.insert(fut) + } + None => return Poll::Ready(Ok(0)), + } + } + }; + let result = match Pin::new(fut).poll(cx) { + Poll::Ready(result) => result, + Poll::Pending => return Poll::Pending, + }; + // Clear slot for next `read()`. + stream.fut = None; + + match result { + Ok(result) => { + let result = result.unchecked_into::(); + match result.is_done() { + true => { + // Drop the readable stream. + stream.inner = None; + Poll::Ready(Ok(0)) + } + false => { + let value = result.value().unwrap_throw(); + let length = value.byte_length() as usize; + + value.copy_to(buf); + + Poll::Ready(Ok(length)) + } + } + } + Err(e) => Poll::Ready(Err(Error::new( + ErrorKind::Other, + js_sys::Object::try_from(&e) + .map(|e| e.to_string().as_string().unwrap_throw()) + .unwrap_or("Unknown error".to_string()), + ))), + } + } + ParserStream::Buffer(ref mut buffer) => { + // Put the requested bytes into the buffer and + // assign the remaining bytes back into the sink. + let amt = std::cmp::min(buffer.len(), buf.len()); + let (a, b) = buffer.split_at(amt); + buf[..amt].copy_from_slice(a); + *buffer = b.to_vec(); + Poll::Ready(Ok(amt)) + } } } } -pub struct Module { - pub specifier: String, - pub kind: ModuleKind, - inner: ModuleInner, -} +type LoaderFut = + Pin, eszip::ParseError>>>>; +type ParseResult = (eszip::EszipV2, LoaderFut); -pub enum ModuleInner { - V1(EszipV1), - V2(EszipV2Modules), +#[wasm_bindgen] +pub struct Parser { + parser: Rc>>>, } -impl Module { - /// Get source code of the module. - pub async fn source(&self) -> Option> { - match &self.inner { - ModuleInner::V1(eszip_v1) => eszip_v1.get_module_source(&self.specifier), - ModuleInner::V2(eszip_v2) => { - eszip_v2.get_module_source(&self.specifier).await - } +#[wasm_bindgen] +impl Parser { + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + Self { + parser: Rc::new(RefCell::new(None)), } } - /// Take source code of the module. This will remove the source code from memory and - /// the subsequent calls to `take_source()` will return `None`. - /// For V1, this will take the entire module and returns the source code. We don't need - /// to preserve module metadata for V1. - pub async fn take_source(&self) -> Option> { - match &self.inner { - ModuleInner::V1(eszip_v1) => eszip_v1.take(&self.specifier), - ModuleInner::V2(eszip_v2) => { - eszip_v2.take_module_source(&self.specifier).await - } - } + /// Parse from a BYOB readable stream. + pub fn parse(&self, stream: ReadableStreamByobReader) -> Promise { + let reader = BufReader::new(ParserStream::Byob(Stream::new(stream))); + self.parse_reader(reader) } - /// Get source map of the module. - pub async fn source_map(&self) -> Option> { - match &self.inner { - ModuleInner::V1(_) => None, - ModuleInner::V2(eszip) => { - eszip.get_module_source_map(&self.specifier).await - } - } + /// Parse from an in-memory buffer. + #[wasm_bindgen(js_name = parseBytes)] + pub fn parse_bytes(&self, buffer: Vec) -> Promise { + let reader = BufReader::new(ParserStream::Buffer(buffer)); + self.parse_reader(reader) } - /// Take source map of the module. This will remove the source map from memory and - /// the subsequent calls to `take_source_map()` will return `None`. - pub async fn take_source_map(&self) -> Option> { - match &self.inner { - ModuleInner::V1(_) => None, - ModuleInner::V2(eszip) => { - eszip.take_module_source_map(&self.specifier).await - } - } + fn parse_reader(&self, reader: BufReader) -> Promise { + let parser = Rc::clone(&self.parser); + + wasm_bindgen_futures::future_to_promise(async move { + let (eszip, loader) = eszip::EszipV2::parse(reader).await.unwrap(); + let specifiers = eszip.specifiers(); + parser.borrow_mut().replace((eszip, Box::pin(loader))); + Ok( + specifiers + .iter() + .map(JsValue::from) + .collect::() + .into(), + ) + }) } -} - -/// This is the kind of module that is being stored. This is the same enum as is -/// present in [deno_core::ModuleType] except that this has additional variant -/// `Jsonc` which is used when an import map is embedded in Deno's config file -/// that can be JSONC. -/// Note that a module of type `Jsonc` can be used only as an import map, not as -/// a normal module. -#[repr(u8)] -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "lowercase")] -pub enum ModuleKind { - JavaScript = 0, - Json = 1, - Jsonc = 2, - OpaqueData = 3, - Wasm = 4, -} -#[cfg(test)] -mod tests { - use super::*; - use futures::StreamExt; - use futures::TryStreamExt; - use futures::io::AllowStdIo; - use futures::stream; - - #[tokio::test] - async fn parse_v1() { - let file = std::fs::File::open("./src/testdata/basic.json").unwrap(); - let (eszip, fut) = Eszip::parse(AllowStdIo::new(file)).await.unwrap(); - fut.await.unwrap(); - assert!(matches!(eszip, Eszip::V1(_))); - eszip.get_module("https://gist.githubusercontent.com/lucacasonato/f3e21405322259ca4ed155722390fda2/raw/e25acb49b681e8e1da5a2a33744b7a36d538712d/hello.js").unwrap(); - } + /// Load module sources. + pub fn load(&mut self) -> Promise { + let parser = Rc::clone(&self.parser); - #[cfg(feature = "sha256")] - #[tokio::test] - async fn parse_v2() { - let file = std::fs::File::open("./src/testdata/redirect.eszip2").unwrap(); - let (eszip, fut) = Eszip::parse(AllowStdIo::new(file)).await.unwrap(); - fut.await.unwrap(); - assert!(matches!(eszip, Eszip::V2(_))); - eszip.get_module("file:///main.ts").unwrap(); + wasm_bindgen_futures::future_to_promise(async move { + let mut p = parser.borrow_mut(); + let (_, loader) = p.as_mut().unwrap_throw(); + loader.await.unwrap(); + Ok(JsValue::UNDEFINED) + }) } - #[tokio::test] - async fn take_source_v1() { - let file = std::fs::File::open("./src/testdata/basic.json").unwrap(); - let (eszip, fut) = Eszip::parse(AllowStdIo::new(file)).await.unwrap(); - fut.await.unwrap(); - assert!(matches!(eszip, Eszip::V1(_))); - let specifier = "https://gist.githubusercontent.com/lucacasonato/f3e21405322259ca4ed155722390fda2/raw/e25acb49b681e8e1da5a2a33744b7a36d538712d/hello.js"; - let module = eszip.get_module(specifier).unwrap(); - assert_eq!(module.specifier, specifier); - // We're taking the source from memory. - let source = module.take_source().await.unwrap(); - assert!(!source.is_empty()); - // Source maps are not supported in v1 and should always return None. - assert!(module.source_map().await.is_none()); - // Module shouldn't be available anymore. - assert!(eszip.get_module(specifier).is_none()); + /// Get a module source. + #[wasm_bindgen(js_name = getModuleSource)] + pub fn get_module_source(&self, specifier: String) -> Promise { + let parser = Rc::clone(&self.parser); + + wasm_bindgen_futures::future_to_promise(async move { + let p = parser.borrow(); + let (eszip, _) = p.as_ref().unwrap(); + let module = eszip + .get_module(&specifier) + .or_else(|| eszip.get_import_map(&specifier)) + .ok_or(TypeError::new(&format!("module '{}' not found", specifier)))?; + + // Drop the borrow for the loader + // to mutably borrow. + drop(p); + let source = module.source().await.ok_or(TypeError::new(&format!( + "source for '{}' already taken", + specifier + )))?; + let source = std::str::from_utf8(&source).unwrap(); + Ok(source.to_string().into()) + }) } - #[cfg(feature = "sha256")] - #[tokio::test] - async fn take_source_v2() { - let file = std::fs::File::open("./src/testdata/redirect.eszip2").unwrap(); - let (eszip, fut) = Eszip::parse(AllowStdIo::new(file)).await.unwrap(); - fut.await.unwrap(); - assert!(matches!(eszip, Eszip::V2(_))); - let specifier = "file:///main.ts"; - let module = eszip.get_module(specifier).unwrap(); - // We're taking the source from memory. - let source = module.take_source().await.unwrap(); - assert!(!source.is_empty()); - let module = eszip.get_module(specifier).unwrap(); - assert_eq!(module.specifier, specifier); - // Source shouldn't be available anymore. - assert!(module.source().await.is_none()); - // We didn't take the source map, so it should still be available. - assert!(module.source_map().await.is_some()); - // Now we're taking the source map. - let source_map = module.take_source_map().await.unwrap(); - assert!(!source_map.is_empty()); - // Source map shouldn't be available anymore. - assert!(module.source_map().await.is_none()); + /// Get a module sourcemap. + #[wasm_bindgen(js_name = getModuleSourceMap)] + pub fn get_module_source_map(&self, specifier: String) -> Promise { + let parser = Rc::clone(&self.parser); + + wasm_bindgen_futures::future_to_promise(async move { + let p = parser.borrow(); + let (eszip, _) = p.as_ref().unwrap(); + let module = eszip + .get_module(&specifier) + .or_else(|| eszip.get_import_map(&specifier)) + .ok_or(TypeError::new(&format!("module '{}' not found", specifier)))?; + + // Drop the borrow for the loader + // to mutably borrow. + drop(p); + match module.source_map().await { + Some(source_map) => { + let source_map = std::str::from_utf8(&source_map).unwrap(); + Ok(source_map.to_string().into()) + } + None => Ok(JsValue::NULL), + } + }) } +} - #[tokio::test] - async fn test_eszip_v1_iterator() { - let file = std::fs::File::open("./src/testdata/basic.json").unwrap(); - let (eszip, fut) = Eszip::parse(AllowStdIo::new(file)).await.unwrap(); - tokio::spawn(fut); - assert!(matches!(eszip, Eszip::V1(_))); - - struct Expected { - specifier: String, - source: &'static str, - kind: ModuleKind, +/// Serialize a module graph into eszip. +#[wasm_bindgen(js_name = build)] +pub async fn build_eszip( + roots: JsValue, + loader: js_sys::Function, + import_map_url: JsValue, +) -> Result { + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + let roots: Vec = + serde_wasm_bindgen::from_value(roots) + .map_err(|e| js_sys::Error::new(&e.to_string()))?; + let loader = GraphLoader(loader); + let import_map_url: Option = + serde_wasm_bindgen::from_value(import_map_url) + .map_err(|e| js_sys::Error::new(&e.to_string()))?; + let (maybe_import_map, maybe_import_map_data) = if let Some(import_map_url) = + import_map_url + { + let resp = deno_graph::source::Loader::load( + &loader, + &import_map_url, + deno_graph::source::LoadOptions { + in_dynamic_branch: false, + was_dynamic_root: false, + cache_setting: deno_graph::source::CacheSetting::Use, + maybe_checksum: None, + }, + ) + .await + .map_err(|e| js_sys::Error::new(&e.to_string()))? + .ok_or_else(|| { + js_sys::Error::new(&format!("import map not found at '{import_map_url}'")) + })?; + match resp { + deno_graph::source::LoadResponse::Module { + specifier, content, .. + } => { + let import_map = import_map::parse_from_json_with_options( + specifier.clone(), + &String::from_utf8(content.to_vec()).unwrap(), + import_map::ImportMapOptions { + address_hook: None, + // always do this for simplicity + expand_imports: true, + }, + ) + .unwrap(); + (Some(import_map.import_map), Some((specifier, content))) + } + _ => unimplemented!(), } - - let expected = vec![ - Expected { - specifier: "https://gist.githubusercontent.com/lucacasonato/f3e21405322259ca4ed155722390fda2/raw/e25acb49b681e8e1da5a2a33744b7a36d538712d/hello.js".to_string(), - source: "addEventListener(\"fetch\", (event)=>{\n event.respondWith(new Response(\"Hello World\", {\n headers: {\n \"content-type\": \"text/plain\"\n }\n }));\n});\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2dpc3QuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2x1Y2FjYXNvbmF0by9mM2UyMTQwNTMyMjI1OWNhNGVkMTU1NzIyMzkwZmRhMi9yYXcvZTI1YWNiNDliNjgxZThlMWRhNWEyYTMzNzQ0YjdhMzZkNTM4NzEyZC9oZWxsby5qcz4iXSwic291cmNlc0NvbnRlbnQiOlsiYWRkRXZlbnRMaXN0ZW5lcihcImZldGNoXCIsIChldmVudCkgPT4ge1xuICBldmVudC5yZXNwb25kV2l0aChuZXcgUmVzcG9uc2UoXCJIZWxsbyBXb3JsZFwiLCB7XG4gICAgaGVhZGVyczogeyBcImNvbnRlbnQtdHlwZVwiOiBcInRleHQvcGxhaW5cIiB9LFxuICB9KSk7XG59KTsiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZ0JBQUEsRUFBQSxLQUFBLElBQUEsS0FBQTtBQUNBLFNBQUEsQ0FBQSxXQUFBLEtBQUEsUUFBQSxFQUFBLFdBQUE7QUFDQSxlQUFBO2FBQUEsWUFBQSxJQUFBLFVBQUEifQ==", - kind: ModuleKind::JavaScript, + } else { + (None, None) + }; + let resolver = GraphResolver(maybe_import_map); + let analyzer = deno_graph::ast::CapturingModuleAnalyzer::default(); + let mut graph = ModuleGraph::new(GraphKind::CodeOnly); + graph + .build( + roots, + Vec::new(), + &loader, + BuildOptions { + resolver: Some(&resolver), + module_analyzer: &analyzer, + file_system: &sys_traits::impls::RealSys, + ..Default::default() }, - ]; + ) + .await; + graph + .valid() + .map_err(|e| js_sys::Error::new(&e.to_string()))?; + let mut eszip = eszip::EszipV2::from_graph(eszip::FromGraphOptions { + graph, + module_kind_resolver: Default::default(), + parser: analyzer.as_capturing_parser(), + transpile_options: Default::default(), + emit_options: Default::default(), + relative_file_base: None, + npm_packages: None, + npm_snapshot: Default::default(), + }) + .map_err(|e| js_sys::Error::new(&e.to_string()))?; + if let Some((import_map_specifier, import_map_content)) = + maybe_import_map_data + { + eszip.add_import_map( + ModuleKind::Json, + import_map_specifier.to_string(), + Arc::from(import_map_content), + ) + } + Ok(Uint8Array::from(eszip.into_bytes().as_slice())) +} - for (got, expected) in eszip.into_iter().zip(expected) { - let (got_specifier, got_module) = got; +// Taken from deno_graph +// https://github.com/denoland/deno_graph/blob/main/src/js_graph.rs#L43 +pub struct GraphLoader(js_sys::Function); - assert_eq!(got_specifier, expected.specifier); - assert_eq!(got_module.kind, expected.kind); - assert_eq!( - String::from_utf8_lossy(&got_module.source().await.unwrap()), - expected.source - ); - } +impl Loader for GraphLoader { + fn get_cache_info(&self, _: &ModuleSpecifier) -> Option { + None } - #[cfg(feature = "sha256")] - #[tokio::test] - async fn test_eszip_v2_iterator() { - let file = std::fs::File::open("./src/testdata/redirect.eszip2").unwrap(); - let (eszip, fut) = Eszip::parse(AllowStdIo::new(file)).await.unwrap(); - tokio::spawn(fut); - assert!(matches!(eszip, Eszip::V2(_))); - - struct Expected { - specifier: String, - source: &'static str, - kind: ModuleKind, + fn load( + &self, + specifier: &ModuleSpecifier, + options: LoadOptions, + ) -> LoadFuture { + #[derive(Serialize)] + #[serde(rename_all = "camelCase")] + struct JsLoadOptions { + pub is_dynamic: bool, + pub cache_setting: &'static str, + pub checksum: Option, } - let expected = vec![ - Expected { - specifier: "file:///main.ts".to_string(), - source: "export * as a from \"./a.ts\";\n", - kind: ModuleKind::JavaScript, - }, - Expected { - specifier: "file:///b.ts".to_string(), - source: "export const b = \"b\";\n", - kind: ModuleKind::JavaScript, - }, - Expected { - specifier: "file:///a.ts".to_string(), - source: "export const b = \"b\";\n", - kind: ModuleKind::JavaScript, - }, - ]; - - for (got, expected) in eszip.into_iter().zip(expected) { - let (got_specifier, got_module) = got; - - assert_eq!(got_specifier, expected.specifier); - assert_eq!(got_module.kind, expected.kind); - assert_eq!( - String::from_utf8_lossy(&got_module.source().await.unwrap()), - expected.source + if specifier.scheme() == "data" { + Box::pin(std::future::ready(load_data_url(specifier).map_err( + |err| { + deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::from_err( + err, + ))) + }, + ))) + } else { + let specifier = specifier.clone(); + let result = self.0.call2( + &JsValue::null(), + &JsValue::from(specifier.to_string()), + &serde_wasm_bindgen::to_value(&JsLoadOptions { + is_dynamic: options.in_dynamic_branch, + cache_setting: options.cache_setting.as_js_str(), + checksum: options.maybe_checksum.map(|c| c.into_string()), + }) + .unwrap(), ); + Box::pin(async move { + let response = match result { + Ok(result) => { + wasm_bindgen_futures::JsFuture::from(js_sys::Promise::resolve( + &result, + )) + .await + } + Err(err) => Err(err), + }; + response + .map(|value| serde_wasm_bindgen::from_value(value).unwrap()) + .map_err(|err| { + let err_str = err + .as_string() + .unwrap_or_else(|| "an error occured during loading".to_string()); + deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::generic( + err_str, + ))) + }) + }) } } +} - #[tokio::test] - async fn parse_small_chunks_reader() { - let bytes = std::fs::read("./src/testdata/redirect.eszip2") - .unwrap() - .chunks(2) - .map(|chunk| chunk.to_vec()) - .collect::>(); - let reader = stream::iter(bytes) - .map(std::io::Result::Ok) - .into_async_read(); - - let (eszip, fut) = Eszip::parse(reader).await.unwrap(); - fut.await.unwrap(); - assert!(matches!(eszip, Eszip::V2(_))); +#[derive(Debug)] +pub struct GraphResolver(Option); + +impl Resolver for GraphResolver { + fn resolve( + &self, + specifier: &str, + referrer_range: &deno_graph::Range, + _kind: deno_graph::source::ResolutionKind, + ) -> Result { + if let Some(import_map) = &self.0 { + import_map + .resolve(specifier, &referrer_range.specifier) + .map_err(ResolveError::from_err) + } else { + Ok(deno_graph::resolve_import( + specifier, + &referrer_range.specifier, + )?) + } } } diff --git a/src/snapshots/eszip__v2__tests__file_format_roundtrippable.snap b/src/snapshots/eszip__v2__tests__file_format_roundtrippable.snap deleted file mode 100644 index 7cf1733..0000000 --- a/src/snapshots/eszip__v2__tests__file_format_roundtrippable.snap +++ /dev/null @@ -1,719 +0,0 @@ ---- -source: src/v2.rs -expression: bytes ---- -[ - 69, - 83, - 90, - 73, - 80, - 50, - 46, - 51, - 0, - 0, - 0, - 4, - 0, - 1, - 1, - 32, - 93, - 165, - 28, - 55, - 117, - 128, - 240, - 183, - 115, - 90, - 129, - 122, - 136, - 28, - 245, - 21, - 233, - 64, - 253, - 55, - 203, - 126, - 13, - 171, - 123, - 185, - 36, - 119, - 36, - 75, - 26, - 21, - 0, - 0, - 0, - 104, - 0, - 0, - 0, - 15, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 109, - 97, - 105, - 110, - 46, - 116, - 115, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 151, - 0, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 0, - 0, - 0, - 0, - 61, - 0, - 0, - 0, - 22, - 0, - 0, - 0, - 183, - 0, - 0, - 0, - 151, - 0, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 97, - 46, - 116, - 115, - 1, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 72, - 28, - 222, - 153, - 19, - 208, - 7, - 135, - 152, - 187, - 213, - 35, - 44, - 124, - 73, - 98, - 68, - 248, - 37, - 203, - 153, - 163, - 243, - 141, - 149, - 244, - 226, - 122, - 96, - 73, - 232, - 144, - 0, - 0, - 0, - 0, - 227, - 176, - 196, - 66, - 152, - 252, - 28, - 20, - 154, - 251, - 244, - 200, - 153, - 111, - 185, - 36, - 39, - 174, - 65, - 228, - 100, - 155, - 147, - 76, - 164, - 149, - 153, - 27, - 120, - 82, - 184, - 85, - 0, - 0, - 0, - 115, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 42, - 32, - 97, - 115, - 32, - 97, - 32, - 102, - 114, - 111, - 109, - 32, - 34, - 46, - 47, - 97, - 46, - 116, - 115, - 34, - 59, - 10, - 47, - 43, - 32, - 46, - 117, - 220, - 233, - 51, - 234, - 223, - 154, - 133, - 115, - 170, - 205, - 173, - 253, - 179, - 31, - 174, - 255, - 191, - 245, - 128, - 155, - 184, - 97, - 88, - 208, - 31, - 136, - 210, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 99, - 111, - 110, - 115, - 116, - 32, - 98, - 32, - 61, - 32, - 34, - 98, - 34, - 59, - 10, - 195, - 125, - 168, - 132, - 12, - 51, - 241, - 62, - 31, - 13, - 95, - 201, - 65, - 196, - 80, - 30, - 66, - 11, - 109, - 88, - 13, - 143, - 234, - 241, - 249, - 0, - 6, - 233, - 191, - 196, - 22, - 196, - 0, - 0, - 1, - 110, - 123, - 34, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 34, - 58, - 51, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 34, - 58, - 91, - 34, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 109, - 97, - 105, - 110, - 46, - 116, - 115, - 34, - 93, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 34, - 58, - 91, - 34, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 42, - 32, - 97, - 115, - 32, - 97, - 32, - 102, - 114, - 111, - 109, - 32, - 92, - 34, - 46, - 47, - 97, - 46, - 116, - 115, - 92, - 34, - 59, - 92, - 110, - 34, - 93, - 44, - 34, - 110, - 97, - 109, - 101, - 115, - 34, - 58, - 91, - 93, - 44, - 34, - 109, - 97, - 112, - 112, - 105, - 110, - 103, - 115, - 34, - 58, - 34, - 65, - 65, - 65, - 65, - 44, - 77, - 65, - 65, - 77, - 44, - 77, - 65, - 65, - 77, - 44, - 67, - 65, - 65, - 67, - 44, - 77, - 65, - 65, - 77, - 44, - 67, - 65, - 65, - 81, - 34, - 125, - 217, - 253, - 126, - 48, - 67, - 114, - 34, - 179, - 49, - 61, - 214, - 16, - 190, - 14, - 207, - 9, - 127, - 94, - 228, - 37, - 155, - 212, - 243, - 253, - 179, - 32, - 161, - 74, - 181, - 190, - 243, - 94, - 123, - 34, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 34, - 58, - 51, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 34, - 58, - 91, - 34, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 34, - 93, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 34, - 58, - 91, - 34, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 99, - 111, - 110, - 115, - 116, - 32, - 98, - 32, - 61, - 32, - 92, - 34, - 98, - 92, - 34, - 59, - 92, - 110, - 34, - 93, - 44, - 34, - 110, - 97, - 109, - 101, - 115, - 34, - 58, - 91, - 93, - 44, - 34, - 109, - 97, - 112, - 112, - 105, - 110, - 103, - 115, - 34, - 58, - 34, - 65, - 65, - 65, - 65, - 44, - 77, - 65, - 65, - 77, - 44, - 67, - 65, - 65, - 67, - 44, - 75, - 65, - 65, - 75, - 44, - 67, - 65, - 65, - 67, - 44, - 67, - 65, - 65, - 67, - 44, - 71, - 65, - 65, - 71, - 44, - 67, - 65, - 65, - 71, - 34, - 125, - 108, - 118, - 224, - 22, - 49, - 2, - 139, - 84, - 17, - 178, - 219, - 36, - 167, - 159, - 14, - 66, - 118, - 252, - 4, - 108, - 73, - 29, - 44, - 69, - 146, - 142, - 207, - 61, - 11, - 157, - 41, - 9, -] diff --git a/src/snapshots/eszip__v2__tests__npm_empty_snapshot.snap b/src/snapshots/eszip__v2__tests__npm_empty_snapshot.snap deleted file mode 100644 index 1c37874..0000000 --- a/src/snapshots/eszip__v2__tests__npm_empty_snapshot.snap +++ /dev/null @@ -1,480 +0,0 @@ ---- -source: src/v2.rs -expression: bytes ---- -[ - 69, - 83, - 90, - 73, - 80, - 50, - 46, - 51, - 0, - 0, - 0, - 4, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 104, - 0, - 0, - 0, - 15, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 109, - 97, - 105, - 110, - 46, - 116, - 115, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 151, - 0, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 0, - 0, - 0, - 0, - 29, - 0, - 0, - 0, - 22, - 0, - 0, - 0, - 151, - 0, - 0, - 0, - 136, - 0, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 97, - 46, - 116, - 115, - 1, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 51, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 42, - 32, - 97, - 115, - 32, - 97, - 32, - 102, - 114, - 111, - 109, - 32, - 34, - 46, - 47, - 97, - 46, - 116, - 115, - 34, - 59, - 10, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 99, - 111, - 110, - 115, - 116, - 32, - 98, - 32, - 61, - 32, - 34, - 98, - 34, - 59, - 10, - 0, - 0, - 1, - 31, - 123, - 34, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 34, - 58, - 51, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 34, - 58, - 91, - 34, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 109, - 97, - 105, - 110, - 46, - 116, - 115, - 34, - 93, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 34, - 58, - 91, - 34, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 42, - 32, - 97, - 115, - 32, - 97, - 32, - 102, - 114, - 111, - 109, - 32, - 92, - 34, - 46, - 47, - 97, - 46, - 116, - 115, - 92, - 34, - 59, - 92, - 110, - 34, - 93, - 44, - 34, - 110, - 97, - 109, - 101, - 115, - 34, - 58, - 91, - 93, - 44, - 34, - 109, - 97, - 112, - 112, - 105, - 110, - 103, - 115, - 34, - 58, - 34, - 65, - 65, - 65, - 65, - 44, - 79, - 65, - 65, - 79, - 44, - 75, - 65, - 65, - 75, - 44, - 67, - 65, - 65, - 67, - 44, - 77, - 65, - 65, - 77, - 44, - 83, - 65, - 65, - 83, - 34, - 125, - 123, - 34, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 34, - 58, - 51, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 34, - 58, - 91, - 34, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 34, - 93, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 34, - 58, - 91, - 34, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 99, - 111, - 110, - 115, - 116, - 32, - 98, - 32, - 61, - 32, - 92, - 34, - 98, - 92, - 34, - 59, - 92, - 110, - 34, - 93, - 44, - 34, - 110, - 97, - 109, - 101, - 115, - 34, - 58, - 91, - 93, - 44, - 34, - 109, - 97, - 112, - 112, - 105, - 110, - 103, - 115, - 34, - 58, - 34, - 65, - 65, - 65, - 65, - 44, - 79, - 65, - 65, - 79, - 44, - 77, - 65, - 65, - 77, - 44, - 73, - 65, - 65, - 73, - 44, - 73, - 65, - 65, - 73, - 34, - 125, -] diff --git a/src/snapshots/eszip__v2__tests__npm_packages.snap b/src/snapshots/eszip__v2__tests__npm_packages.snap deleted file mode 100644 index 3a0f2d6..0000000 --- a/src/snapshots/eszip__v2__tests__npm_packages.snap +++ /dev/null @@ -1,690 +0,0 @@ ---- -source: src/v2.rs -expression: bytes ---- -[ - 69, - 83, - 90, - 73, - 80, - 50, - 46, - 51, - 0, - 0, - 0, - 4, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 156, - 0, - 0, - 0, - 15, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 109, - 97, - 105, - 110, - 46, - 116, - 115, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 151, - 0, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 0, - 0, - 0, - 0, - 29, - 0, - 0, - 0, - 22, - 0, - 0, - 0, - 151, - 0, - 0, - 0, - 136, - 0, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 97, - 46, - 116, - 115, - 1, - 0, - 0, - 0, - 12, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 0, - 0, - 0, - 3, - 100, - 64, - 53, - 2, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 12, - 112, - 97, - 99, - 107, - 97, - 103, - 101, - 64, - 94, - 49, - 46, - 50, - 2, - 0, - 0, - 0, - 5, - 0, - 0, - 0, - 10, - 112, - 97, - 99, - 107, - 97, - 103, - 101, - 64, - 94, - 49, - 2, - 0, - 0, - 0, - 5, - 0, - 0, - 0, - 158, - 0, - 0, - 0, - 7, - 97, - 64, - 50, - 46, - 50, - 46, - 51, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7, - 98, - 64, - 49, - 46, - 50, - 46, - 51, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 18, - 115, - 111, - 109, - 101, - 111, - 116, - 104, - 101, - 114, - 115, - 112, - 101, - 99, - 105, - 102, - 105, - 101, - 114, - 0, - 0, - 0, - 2, - 0, - 0, - 0, - 7, - 99, - 64, - 49, - 46, - 49, - 46, - 49, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7, - 100, - 64, - 53, - 46, - 48, - 46, - 48, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1, - 101, - 0, - 0, - 0, - 4, - 0, - 0, - 0, - 7, - 101, - 64, - 54, - 46, - 48, - 46, - 48, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1, - 100, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 13, - 112, - 97, - 99, - 107, - 97, - 103, - 101, - 64, - 49, - 46, - 50, - 46, - 50, - 0, - 0, - 0, - 2, - 0, - 0, - 0, - 1, - 97, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 98, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 51, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 42, - 32, - 97, - 115, - 32, - 97, - 32, - 102, - 114, - 111, - 109, - 32, - 34, - 46, - 47, - 97, - 46, - 116, - 115, - 34, - 59, - 10, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 99, - 111, - 110, - 115, - 116, - 32, - 98, - 32, - 61, - 32, - 34, - 98, - 34, - 59, - 10, - 0, - 0, - 1, - 31, - 123, - 34, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 34, - 58, - 51, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 34, - 58, - 91, - 34, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 109, - 97, - 105, - 110, - 46, - 116, - 115, - 34, - 93, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 34, - 58, - 91, - 34, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 42, - 32, - 97, - 115, - 32, - 97, - 32, - 102, - 114, - 111, - 109, - 32, - 92, - 34, - 46, - 47, - 97, - 46, - 116, - 115, - 92, - 34, - 59, - 92, - 110, - 34, - 93, - 44, - 34, - 110, - 97, - 109, - 101, - 115, - 34, - 58, - 91, - 93, - 44, - 34, - 109, - 97, - 112, - 112, - 105, - 110, - 103, - 115, - 34, - 58, - 34, - 65, - 65, - 65, - 65, - 44, - 79, - 65, - 65, - 79, - 44, - 75, - 65, - 65, - 75, - 44, - 67, - 65, - 65, - 67, - 44, - 77, - 65, - 65, - 77, - 44, - 83, - 65, - 65, - 83, - 34, - 125, - 123, - 34, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 34, - 58, - 51, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 34, - 58, - 91, - 34, - 102, - 105, - 108, - 101, - 58, - 47, - 47, - 47, - 98, - 46, - 116, - 115, - 34, - 93, - 44, - 34, - 115, - 111, - 117, - 114, - 99, - 101, - 115, - 67, - 111, - 110, - 116, - 101, - 110, - 116, - 34, - 58, - 91, - 34, - 101, - 120, - 112, - 111, - 114, - 116, - 32, - 99, - 111, - 110, - 115, - 116, - 32, - 98, - 32, - 61, - 32, - 92, - 34, - 98, - 92, - 34, - 59, - 92, - 110, - 34, - 93, - 44, - 34, - 110, - 97, - 109, - 101, - 115, - 34, - 58, - 91, - 93, - 44, - 34, - 109, - 97, - 112, - 112, - 105, - 110, - 103, - 115, - 34, - 58, - 34, - 65, - 65, - 65, - 65, - 44, - 79, - 65, - 65, - 79, - 44, - 77, - 65, - 65, - 77, - 44, - 73, - 65, - 65, - 73, - 44, - 73, - 65, - 65, - 73, - 34, - 125, -] diff --git a/src/snapshots/eszip__v2__tests__opaque_data.snap b/src/snapshots/eszip__v2__tests__opaque_data.snap deleted file mode 100644 index b7a3c51..0000000 --- a/src/snapshots/eszip__v2__tests__opaque_data.snap +++ /dev/null @@ -1,72 +0,0 @@ ---- -source: src/v2.rs -expression: bytes ---- -[ - 69, - 83, - 90, - 73, - 80, - 50, - 46, - 51, - 0, - 0, - 0, - 4, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 31, - 0, - 0, - 0, - 9, - 43, - 115, - 47, - 102, - 111, - 111, - 98, - 97, - 114, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3, - 1, - 2, - 3, - 0, - 0, - 0, - 0, -] diff --git a/src/testdata/basic.json b/src/testdata/basic.json deleted file mode 100644 index 7ec06aa..0000000 --- a/src/testdata/basic.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": 1, - "modules": { - "https://gist.githubusercontent.com/lucacasonato/f3e21405322259ca4ed155722390fda2/raw/e25acb49b681e8e1da5a2a33744b7a36d538712d/hello.js": { - "Source": { - "source": "addEventListener(\"fetch\", (event) => {\n event.respondWith(new Response(\"Hello World\", {\n headers: { \"content-type\": \"text/plain\" },\n }));\n});", - "transpiled": "addEventListener(\"fetch\", (event)=>{\n event.respondWith(new Response(\"Hello World\", {\n headers: {\n \"content-type\": \"text/plain\"\n }\n }));\n});\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2dpc3QuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2x1Y2FjYXNvbmF0by9mM2UyMTQwNTMyMjI1OWNhNGVkMTU1NzIyMzkwZmRhMi9yYXcvZTI1YWNiNDliNjgxZThlMWRhNWEyYTMzNzQ0YjdhMzZkNTM4NzEyZC9oZWxsby5qcz4iXSwic291cmNlc0NvbnRlbnQiOlsiYWRkRXZlbnRMaXN0ZW5lcihcImZldGNoXCIsIChldmVudCkgPT4ge1xuICBldmVudC5yZXNwb25kV2l0aChuZXcgUmVzcG9uc2UoXCJIZWxsbyBXb3JsZFwiLCB7XG4gICAgaGVhZGVyczogeyBcImNvbnRlbnQtdHlwZVwiOiBcInRleHQvcGxhaW5cIiB9LFxuICB9KSk7XG59KTsiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZ0JBQUEsRUFBQSxLQUFBLElBQUEsS0FBQTtBQUNBLFNBQUEsQ0FBQSxXQUFBLEtBQUEsUUFBQSxFQUFBLFdBQUE7QUFDQSxlQUFBO2FBQUEsWUFBQSxJQUFBLFVBQUEifQ==", - "content_type": "text/plain; charset=utf-8", - "deps": [] - } - } - } -} diff --git a/src/testdata/deno_jsonc_as_import_map/a.ts b/src/testdata/deno_jsonc_as_import_map/a.ts deleted file mode 100644 index 59d1689..0000000 --- a/src/testdata/deno_jsonc_as_import_map/a.ts +++ /dev/null @@ -1 +0,0 @@ -export const b = "b"; diff --git a/src/testdata/deno_jsonc_as_import_map/deno.jsonc b/src/testdata/deno_jsonc_as_import_map/deno.jsonc deleted file mode 100644 index 44c6bbf..0000000 --- a/src/testdata/deno_jsonc_as_import_map/deno.jsonc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "tasks": { - "run": "deno run main.ts" - }, - // comment - "imports": { - "a": "./a.ts" - } -} diff --git a/src/testdata/deno_jsonc_as_import_map/main.ts b/src/testdata/deno_jsonc_as_import_map/main.ts deleted file mode 100644 index 87e6100..0000000 --- a/src/testdata/deno_jsonc_as_import_map/main.ts +++ /dev/null @@ -1 +0,0 @@ -export * as a from "./a.ts"; diff --git a/src/testdata/dotland.json b/src/testdata/dotland.json deleted file mode 100644 index 47d3ad1..0000000 --- a/src/testdata/dotland.json +++ /dev/null @@ -1,346 +0,0 @@ -{ - "version": 1, - "modules": { - "https://esm.sh/twas@2.1.2": { - "Source": { - "source": "/* esm.sh - twas@2.1.2 */\nexport * from \"https://cdn.esm.sh/v64/twas@2.1.2/deno/twas.js\";\nexport { default } from \"https://cdn.esm.sh/v64/twas@2.1.2/deno/twas.js\";\n", - "transpiled": null, - "content_type": "application/javascript; charset=utf-8", - "deps": [ - "https://cdn.esm.sh/v64/twas@2.1.2/deno/twas.js", - "https://cdn.esm.sh/v64/twas@2.1.2/deno/twas.js" - ] - } - }, - "https://deno.land/std@0.108.0/async/delay.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\nexport interface DelayOptions {\n signal?: AbortSignal;\n}\n\n/* Resolves after the given number of milliseconds. */\nexport function delay(ms: number, options: DelayOptions = {}): Promise {\n const { signal } = options;\n return new Promise((resolve, reject): void => {\n const abort = () => {\n clearTimeout(i);\n reject(new DOMException(\"Delay was aborted.\", \"AbortError\"));\n };\n const done = () => {\n signal?.removeEventListener(\"abort\", abort);\n resolve();\n };\n const i = setTimeout(done, ms);\n signal?.addEventListener(\"abort\", abort, { once: true });\n });\n}\n", - "transpiled": "/* Resolves after the given number of milliseconds. */ export function delay(ms, options = {\n}) {\n const { signal } = options;\n return new Promise((resolve, reject)=>{\n const abort = ()=>{\n clearTimeout(i);\n reject(new DOMException(\"Delay was aborted.\", \"AbortError\"));\n };\n const done = ()=>{\n signal?.removeEventListener(\"abort\", abort);\n resolve();\n };\n const i = setTimeout(done, ms);\n signal?.addEventListener(\"abort\", abort, {\n once: true\n });\n });\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy9kZWxheS50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUEsRUFBc0QsQUFBdEQsa0RBQXNELEFBQXRELEVBQXNELENBQ3RELE1BQU0sVUFBVSxLQUFLLENBQUMsRUFBVSxFQUFFLE9BQXFCLEdBQUcsQ0FBQztBQUFBLENBQUMsRUFBaUIsQ0FBQztJQUM1RSxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBQyxDQUFDLEdBQUcsT0FBTztJQUMxQixNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxHQUFXLENBQUM7UUFDN0MsS0FBSyxDQUFDLEtBQUssT0FBUyxDQUFDO1lBQ25CLFlBQVksQ0FBQyxDQUFDO1lBQ2QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBb0IscUJBQUUsQ0FBWTtRQUM1RCxDQUFDO1FBQ0QsS0FBSyxDQUFDLElBQUksT0FBUyxDQUFDO1lBQ2xCLE1BQU0sRUFBRSxtQkFBbUIsQ0FBQyxDQUFPLFFBQUUsS0FBSztZQUMxQyxPQUFPO1FBQ1QsQ0FBQztRQUNELEtBQUssQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLElBQUksRUFBRSxFQUFFO1FBQzdCLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFPLFFBQUUsS0FBSyxFQUFFLENBQUM7WUFBQyxJQUFJLEVBQUUsSUFBSTtRQUFDLENBQUM7SUFDekQsQ0FBQztBQUNILENBQUMifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/x/oak_commons@0.1.1/negotiation.ts": { - "Source": { - "source": "// Copyright 2018-2021 the oak authors. All rights reserved. MIT license.\n\nimport { preferredEncodings } from \"./negotiation/encoding.ts\";\nimport { preferredLanguages } from \"./negotiation/language.ts\";\nimport { preferredMediaTypes } from \"./negotiation/mediaType.ts\";\n\nexport type Request = {\n headers: {\n get(key: string): string | null;\n };\n};\n\n/** Returns an array of media types accepted by the request, in order of\n * preference. If there are no media types supplied in the request, then any\n * media type selector will be returned. */\nexport function accepts(request: Request): string[];\n/** For a given set of media types, return the best match accepted in the\n * request. If no media type matches, then the function returns `undefined`. */\nexport function accepts(\n request: Request,\n ...types: string[]\n): string | undefined;\nexport function accepts(\n request: Request,\n ...types: string[]\n): string | string[] | undefined {\n const accept = request.headers.get(\"accept\");\n return types.length\n ? accept ? preferredMediaTypes(accept, types)[0] : types[0]\n : accept\n ? preferredMediaTypes(accept)\n : [\"*/*\"];\n}\n\n/** Returns an array of content encodings accepted by the request, in order of\n * preference. If there are no encoding supplied in the request, then `[\"*\"]`\n * is returned, implying any encoding is accepted. */\nexport function acceptsEncodings(request: Request): string[];\n/** For a given set of content encodings, return the best match accepted in the\n * request. If no content encodings match, then the function returns\n * `undefined`.\n *\n * **NOTE:** You should always supply `identity` as one of the encodings\n * to ensure that there is a match when the `Accept-Encoding` header is part\n * of the request. */\nexport function acceptsEncodings(\n request: Request,\n ...encodings: string[]\n): string | undefined;\nexport function acceptsEncodings(\n request: Request,\n ...encodings: string[]\n): string | string[] | undefined {\n const acceptEncoding = request.headers.get(\"accept-encoding\");\n return encodings.length\n ? acceptEncoding\n ? preferredEncodings(acceptEncoding, encodings)[0]\n : encodings[0]\n : acceptEncoding\n ? preferredEncodings(acceptEncoding)\n : [\"*\"];\n}\n\n/** Returns an array of languages accepted by the request, in order of\n * preference. If there are no languages supplied in the request, then `[\"*\"]`\n * is returned, imply any language is accepted. */\nexport function acceptsLanguages(request: Request): string[];\n/** For a given set of languages, return the best match accepted in the request.\n * If no languages match, then the function returns `undefined`. */\nexport function acceptsLanguages(\n request: Request,\n ...langs: string[]\n): string | undefined;\nexport function acceptsLanguages(\n request: Request,\n ...langs: string[]\n): string | string[] | undefined {\n const acceptLanguage = request.headers.get(\"accept-language\");\n return langs.length\n ? acceptLanguage ? preferredLanguages(acceptLanguage, langs)[0] : langs[0]\n : acceptLanguage\n ? preferredLanguages(acceptLanguage)\n : [\"*\"];\n}\n", - "transpiled": "// Copyright 2018-2021 the oak authors. All rights reserved. MIT license.\nimport { preferredEncodings } from \"./negotiation/encoding.ts\";\nimport { preferredLanguages } from \"./negotiation/language.ts\";\nimport { preferredMediaTypes } from \"./negotiation/mediaType.ts\";\nexport function accepts(request, ...types) {\n const accept = request.headers.get(\"accept\");\n return types.length ? accept ? preferredMediaTypes(accept, types)[0] : types[0] : accept ? preferredMediaTypes(accept) : [\n \"*/*\"\n ];\n}\nexport function acceptsEncodings(request, ...encodings) {\n const acceptEncoding = request.headers.get(\"accept-encoding\");\n return encodings.length ? acceptEncoding ? preferredEncodings(acceptEncoding, encodings)[0] : encodings[0] : acceptEncoding ? preferredEncodings(acceptEncoding) : [\n \"*\"\n ];\n}\nexport function acceptsLanguages(request, ...langs) {\n const acceptLanguage = request.headers.get(\"accept-language\");\n return langs.length ? acceptLanguage ? preferredLanguages(acceptLanguage, langs)[0] : langs[0] : acceptLanguage ? preferredLanguages(acceptLanguage) : [\n \"*\"\n ];\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L29ha19jb21tb25zQDAuMS4xL25lZ290aWF0aW9uLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQUF5RSxBQUF6RSx1RUFBeUU7QUFFekUsTUFBTSxHQUFHLGtCQUFrQixRQUFRLENBQTJCO0FBQzlELE1BQU0sR0FBRyxrQkFBa0IsUUFBUSxDQUEyQjtBQUM5RCxNQUFNLEdBQUcsbUJBQW1CLFFBQVEsQ0FBNEI7QUFrQmhFLE1BQU0sVUFBVSxPQUFPLENBQ3JCLE9BQWdCLEtBQ2IsS0FBSyxFQUN1QixDQUFDO0lBQ2hDLEtBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBUTtJQUMzQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FDZixNQUFNLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsSUFDeEQsTUFBTSxHQUNOLG1CQUFtQixDQUFDLE1BQU0sSUFDMUIsQ0FBQztRQUFBLENBQUs7SUFBQSxDQUFDO0FBQ2IsQ0FBQztBQWlCRCxNQUFNLFVBQVUsZ0JBQWdCLENBQzlCLE9BQWdCLEtBQ2IsU0FBUyxFQUNtQixDQUFDO0lBQ2hDLEtBQUssQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBaUI7SUFDNUQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQ25CLGNBQWMsR0FDWixrQkFBa0IsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsSUFDL0MsU0FBUyxDQUFDLENBQUMsSUFDYixjQUFjLEdBQ2Qsa0JBQWtCLENBQUMsY0FBYyxJQUNqQyxDQUFDO1FBQUEsQ0FBRztJQUFBLENBQUM7QUFDWCxDQUFDO0FBWUQsTUFBTSxVQUFVLGdCQUFnQixDQUM5QixPQUFnQixLQUNiLEtBQUssRUFDdUIsQ0FBQztJQUNoQyxLQUFLLENBQUMsY0FBYyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQWlCO0lBQzVELE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUNmLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQyxjQUFjLEVBQUUsS0FBSyxFQUFFLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxJQUN2RSxjQUFjLEdBQ2Qsa0JBQWtCLENBQUMsY0FBYyxJQUNqQyxDQUFDO1FBQUEsQ0FBRztJQUFBLENBQUM7QUFDWCxDQUFDIn0=", - "content_type": "application/typescript; charset=utf-8", - "deps": [ - "https://deno.land/x/oak_commons@0.1.1/negotiation/encoding.ts", - "https://deno.land/x/oak_commons@0.1.1/negotiation/language.ts", - "https://deno.land/x/oak_commons@0.1.1/negotiation/mediaType.ts" - ] - } - }, - "https://deno.land/x/oak_commons@0.1.1/negotiation/common.ts": { - "Source": { - "source": "/*!\n * Adapted directly from negotiator at https://github.com/jshttp/negotiator/\n * which is licensed as follows:\n *\n * (The MIT License)\n *\n * Copyright (c) 2012-2014 Federico Romero\n * Copyright (c) 2012-2014 Isaac Z. Schlueter\n * Copyright (c) 2014-2015 Douglas Christopher Wilson\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nexport interface Specificity {\n i: number;\n o?: number;\n q: number;\n s?: number;\n}\n\nexport function compareSpecs(a: Specificity, b: Specificity): number {\n return (\n b.q - a.q ||\n (b.s ?? 0) - (a.s ?? 0) ||\n (a.o ?? 0) - (b.o ?? 0) ||\n a.i - b.i ||\n 0\n );\n}\n\nexport function isQuality(spec: Specificity): boolean {\n return spec.q > 0;\n}\n", - "transpiled": "export function compareSpecs(a, b) {\n return b.q - a.q || (b.s ?? 0) - (a.s ?? 0) || (a.o ?? 0) - (b.o ?? 0) || a.i - b.i || 0;\n}\nexport function isQuality(spec) {\n return spec.q > 0;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L29ha19jb21tb25zQDAuMS4xL25lZ290aWF0aW9uL2NvbW1vbi50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBcUNBLE1BQU0sVUFBVSxZQUFZLENBQUMsQ0FBYyxFQUFFLENBQWMsRUFBVSxDQUFDO0lBQ3BFLE1BQU0sQ0FDSixDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQ1IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQ3JCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUN0QixDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQ1QsQ0FBQztBQUVMLENBQUM7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUFDLElBQWlCLEVBQVcsQ0FBQztJQUNyRCxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDO0FBQ25CLENBQUMifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/x/oak_commons@0.1.1/negotiation/mediaType.ts": { - "Source": { - "source": "/*!\n * Adapted directly from negotiator at https://github.com/jshttp/negotiator/\n * which is licensed as follows:\n *\n * (The MIT License)\n *\n * Copyright (c) 2012-2014 Federico Romero\n * Copyright (c) 2012-2014 Isaac Z. Schlueter\n * Copyright (c) 2014-2015 Douglas Christopher Wilson\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nimport { compareSpecs, isQuality, Specificity } from \"./common.ts\";\n\ninterface MediaTypeSpecificity extends Specificity {\n type: string;\n subtype: string;\n params: { [param: string]: string | undefined };\n}\n\nconst simpleMediaTypeRegExp = /^\\s*([^\\s\\/;]+)\\/([^;\\s]+)\\s*(?:;(.*))?$/;\n\nfunction quoteCount(str: string): number {\n let count = 0;\n let index = 0;\n\n while ((index = str.indexOf(`\"`, index)) !== -1) {\n count++;\n index++;\n }\n\n return count;\n}\n\nfunction splitMediaTypes(accept: string): string[] {\n const accepts = accept.split(\",\");\n\n let j = 0;\n for (let i = 1; i < accepts.length; i++) {\n if (quoteCount(accepts[j]) % 2 === 0) {\n accepts[++j] = accepts[i];\n } else {\n accepts[j] += `,${accepts[i]}`;\n }\n }\n\n accepts.length = j + 1;\n\n return accepts;\n}\n\nfunction splitParameters(str: string): string[] {\n const parameters = str.split(\";\");\n\n let j = 0;\n for (let i = 1; i < parameters.length; i++) {\n if (quoteCount(parameters[j]) % 2 === 0) {\n parameters[++j] = parameters[i];\n } else {\n parameters[j] += `;${parameters[i]}`;\n }\n }\n\n parameters.length = j + 1;\n\n return parameters.map((p) => p.trim());\n}\n\nfunction splitKeyValuePair(str: string): [string, string | undefined] {\n const [key, value] = str.split(\"=\");\n return [key.toLowerCase(), value];\n}\n\nfunction parseMediaType(\n str: string,\n i: number,\n): MediaTypeSpecificity | undefined {\n const match = simpleMediaTypeRegExp.exec(str);\n\n if (!match) {\n return;\n }\n\n const params: { [param: string]: string | undefined } = Object.create(null);\n let q = 1;\n const [, type, subtype, parameters] = match;\n\n if (parameters) {\n const kvps = splitParameters(parameters).map(splitKeyValuePair);\n\n for (const [key, val] of kvps) {\n const value = val && val[0] === `\"` && val[val.length - 1] === `\"`\n ? val.substr(1, val.length - 2)\n : val;\n\n if (key === \"q\" && value) {\n q = parseFloat(value);\n break;\n }\n\n params[key] = value;\n }\n }\n\n return { type, subtype, params, q, i };\n}\n\nfunction parseAccept(accept: string): MediaTypeSpecificity[] {\n const accepts = splitMediaTypes(accept);\n\n const mediaTypes: MediaTypeSpecificity[] = [];\n for (let i = 0; i < accepts.length; i++) {\n const mediaType = parseMediaType(accepts[i].trim(), i);\n\n if (mediaType) {\n mediaTypes.push(mediaType);\n }\n }\n\n return mediaTypes;\n}\n\nfunction getFullType(spec: MediaTypeSpecificity) {\n return `${spec.type}/${spec.subtype}`;\n}\n\nfunction specify(\n type: string,\n spec: MediaTypeSpecificity,\n index: number,\n): Specificity | undefined {\n const p = parseMediaType(type, index);\n\n if (!p) {\n return;\n }\n\n let s = 0;\n\n if (spec.type.toLowerCase() === p.type.toLowerCase()) {\n s |= 4;\n } else if (spec.type !== \"*\") {\n return;\n }\n\n if (spec.subtype.toLowerCase() === p.subtype.toLowerCase()) {\n s |= 2;\n } else if (spec.subtype !== \"*\") {\n return;\n }\n\n const keys = Object.keys(spec.params);\n if (keys.length) {\n if (\n keys.every((key) =>\n (spec.params[key] || \"\").toLowerCase() ===\n (p.params[key] || \"\").toLowerCase()\n )\n ) {\n s |= 1;\n } else {\n return;\n }\n }\n\n return {\n i: index,\n o: spec.o,\n q: spec.q,\n s,\n };\n}\n\nfunction getMediaTypePriority(\n type: string,\n accepted: MediaTypeSpecificity[],\n index: number,\n) {\n let priority: Specificity = { o: -1, q: 0, s: 0, i: index };\n\n for (const accepts of accepted) {\n const spec = specify(type, accepts, index);\n\n if (\n spec &&\n ((priority.s || 0) - (spec.s || 0) ||\n (priority.q || 0) - (spec.q || 0) ||\n (priority.o || 0) - (spec.o || 0)) < 0\n ) {\n priority = spec;\n }\n }\n\n return priority;\n}\n\nexport function preferredMediaTypes(\n accept?: string | null,\n provided?: string[],\n): string[] {\n const accepts = parseAccept(accept === undefined ? \"*/*\" : accept || \"\");\n\n if (!provided) {\n return accepts\n .filter(isQuality)\n .sort(compareSpecs)\n .map(getFullType);\n }\n\n const priorities = provided.map((type, index) => {\n return getMediaTypePriority(type, accepts, index);\n });\n\n return priorities\n .filter(isQuality)\n .sort(compareSpecs)\n .map((priority) => provided[priorities.indexOf(priority)]);\n}\n", - "transpiled": "/*!\n * Adapted directly from negotiator at https://github.com/jshttp/negotiator/\n * which is licensed as follows:\n *\n * (The MIT License)\n *\n * Copyright (c) 2012-2014 Federico Romero\n * Copyright (c) 2012-2014 Isaac Z. Schlueter\n * Copyright (c) 2014-2015 Douglas Christopher Wilson\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */ import { compareSpecs, isQuality } from \"./common.ts\";\nconst simpleMediaTypeRegExp = /^\\s*([^\\s\\/;]+)\\/([^;\\s]+)\\s*(?:;(.*))?$/;\nfunction quoteCount(str) {\n let count = 0;\n let index = 0;\n while((index = str.indexOf(`\"`, index)) !== -1){\n count++;\n index++;\n }\n return count;\n}\nfunction splitMediaTypes(accept) {\n const accepts = accept.split(\",\");\n let j = 0;\n for(let i = 1; i < accepts.length; i++){\n if (quoteCount(accepts[j]) % 2 === 0) {\n accepts[++j] = accepts[i];\n } else {\n accepts[j] += `,${accepts[i]}`;\n }\n }\n accepts.length = j + 1;\n return accepts;\n}\nfunction splitParameters(str) {\n const parameters = str.split(\";\");\n let j = 0;\n for(let i = 1; i < parameters.length; i++){\n if (quoteCount(parameters[j]) % 2 === 0) {\n parameters[++j] = parameters[i];\n } else {\n parameters[j] += `;${parameters[i]}`;\n }\n }\n parameters.length = j + 1;\n return parameters.map((p)=>p.trim()\n );\n}\nfunction splitKeyValuePair(str) {\n const [key, value] = str.split(\"=\");\n return [\n key.toLowerCase(),\n value\n ];\n}\nfunction parseMediaType(str, i) {\n const match = simpleMediaTypeRegExp.exec(str);\n if (!match) {\n return;\n }\n const params = Object.create(null);\n let q = 1;\n const [, type, subtype, parameters] = match;\n if (parameters) {\n const kvps = splitParameters(parameters).map(splitKeyValuePair);\n for (const [key, val] of kvps){\n const value = val && val[0] === `\"` && val[val.length - 1] === `\"` ? val.substr(1, val.length - 2) : val;\n if (key === \"q\" && value) {\n q = parseFloat(value);\n break;\n }\n params[key] = value;\n }\n }\n return {\n type,\n subtype,\n params,\n q,\n i\n };\n}\nfunction parseAccept(accept) {\n const accepts = splitMediaTypes(accept);\n const mediaTypes = [];\n for(let i = 0; i < accepts.length; i++){\n const mediaType = parseMediaType(accepts[i].trim(), i);\n if (mediaType) {\n mediaTypes.push(mediaType);\n }\n }\n return mediaTypes;\n}\nfunction getFullType(spec) {\n return `${spec.type}/${spec.subtype}`;\n}\nfunction specify(type, spec, index) {\n const p = parseMediaType(type, index);\n if (!p) {\n return;\n }\n let s = 0;\n if (spec.type.toLowerCase() === p.type.toLowerCase()) {\n s |= 4;\n } else if (spec.type !== \"*\") {\n return;\n }\n if (spec.subtype.toLowerCase() === p.subtype.toLowerCase()) {\n s |= 2;\n } else if (spec.subtype !== \"*\") {\n return;\n }\n const keys = Object.keys(spec.params);\n if (keys.length) {\n if (keys.every((key)=>(spec.params[key] || \"\").toLowerCase() === (p.params[key] || \"\").toLowerCase()\n )) {\n s |= 1;\n } else {\n return;\n }\n }\n return {\n i: index,\n o: spec.o,\n q: spec.q,\n s\n };\n}\nfunction getMediaTypePriority(type, accepted, index) {\n let priority = {\n o: -1,\n q: 0,\n s: 0,\n i: index\n };\n for (const accepts of accepted){\n const spec = specify(type, accepts, index);\n if (spec && ((priority.s || 0) - (spec.s || 0) || (priority.q || 0) - (spec.q || 0) || (priority.o || 0) - (spec.o || 0)) < 0) {\n priority = spec;\n }\n }\n return priority;\n}\nexport function preferredMediaTypes(accept, provided) {\n const accepts = parseAccept(accept === undefined ? \"*/*\" : accept || \"\");\n if (!provided) {\n return accepts.filter(isQuality).sort(compareSpecs).map(getFullType);\n }\n const priorities = provided.map((type, index)=>{\n return getMediaTypePriority(type, accepts, index);\n });\n return priorities.filter(isQuality).sort(compareSpecs).map((priority)=>provided[priorities.indexOf(priority)]\n );\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L29ha19jb21tb25zQDAuMS4xL25lZ290aWF0aW9uL21lZGlhVHlwZS50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsRUE0QkcsQUE1Qkg7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0E0QkcsQUE1QkgsRUE0QkcsQ0FFSCxNQUFNLEdBQUcsWUFBWSxFQUFFLFNBQVMsUUFBcUIsQ0FBYTtBQVFsRSxLQUFLLENBQUMscUJBQXFCO1NBRWxCLFVBQVUsQ0FBQyxHQUFXLEVBQVUsQ0FBQztJQUN4QyxHQUFHLENBQUMsS0FBSyxHQUFHLENBQUM7SUFDYixHQUFHLENBQUMsS0FBSyxHQUFHLENBQUM7V0FFTCxLQUFLLEdBQUcsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsS0FBSyxRQUFRLENBQUMsQ0FBRSxDQUFDO1FBQ2hELEtBQUs7UUFDTCxLQUFLO0lBQ1AsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFLO0FBQ2QsQ0FBQztTQUVRLGVBQWUsQ0FBQyxNQUFjLEVBQVksQ0FBQztJQUNsRCxLQUFLLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBRztJQUVoQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDVCxHQUFHLENBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFJLENBQUM7UUFDeEMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNyQyxPQUFPLEdBQUcsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDO1FBQzFCLENBQUMsTUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMs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", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/x/oak_commons@0.1.1/negotiation/common.ts"] - } - }, - "file:///src/worker/suggestions.ts": { - "Source": { - "source": "/* Copyright 2021-2022 the Deno authors. All rights reserved. MIT license. */\n\n// @deno-types https://deno.land/x/fuse@v6.4.1/dist/fuse.d.ts\nimport { default as Fuse } from \"https://deno.land/x/fuse@v6.4.1/dist/fuse.esm.js\";\nimport { prettyBytes } from \"https://deno.land/x/pretty_bytes@v1.0.5/mod.ts\";\nimport twas from \"https://esm.sh/twas@2.1.2\";\n\nimport { S3_BUCKET } from \"./registry.ts\";\n\ninterface ApiModuleData {\n name: string;\n description: string;\n \"star_count\": number;\n}\n\ninterface ApiModuleResponse {\n data: ApiModuleData;\n}\n\ninterface ApiModuleSearchResponse {\n data: { results: ApiModuleData[] };\n}\n\ninterface MetaVersionJson {\n latest: string;\n versions: string[];\n}\n\ninterface MetaFileJson {\n path: string;\n size: number;\n type: \"dir\" | \"file\";\n}\n\ninterface MetaJson {\n \"uploaded_at\": string;\n \"directory_listing\": MetaFileJson[];\n \"upload_options\": {\n type: string;\n repository: string;\n ref: string;\n };\n}\n\ninterface PackageData {\n name: string;\n description: string;\n stars: number;\n}\n\nconst MODULE_LIST = \"https://api.deno.land/modules?simple=1\";\nconst INITIAL_LIST = \"https://api.deno.land/modules?limit=50&sort=stars\";\nconst MAX_AGE_1_HOUR = \"max-age=3600\";\nconst MAX_AGE_1_DAY = \"max-age=86400\";\nconst IMMUTABLE = \"max-age=2628000, immutable\";\n\nlet fuse = new Fuse([], { includeScore: true, distance: 10 });\n/** If the index searching hasn't been updated in > 120 seconds, it will be\n * refreshed before processing the next request, meaning the index of packages\n * will be kept fresh. */\nlet fuseUpdated = 0;\n\n/** A cache of all the package data retrieved from api.deno.land.\n *\n * Since this data only contains the description and the star count, which\n * are likely to change slowly, and don't materially impact the responses, the\n * cached values will be reset when the worker is restarted, which is likely\n * sufficient invalidation. */\nconst packages = new Map();\n/** The initial list of packages displayed when there is no specific package\n * being searched for. Currently this will be the top 50 packages/modules in\n * the registry order by star count. */\nlet initialList: string[];\n/** A cache of all the package data retrieved from the S3 bucket. */\nconst packageMeta = new Map>();\n/** A cache of a modules version data retrieved from the S3 bucket. */\nconst versions = new Map();\n/** We will cache versions of packages/modules for up to 5 minutes before\n * considering them state, and clearing them out. */\nlet versionsInvalidated = Date.now();\n\n/** Descriptions of the packages/modules that are in `std`.\n *\n * TODO(@kitsonk): move to `std` as a JSON file which is retrieved. */\nconst stdDescriptions: Record = {\n archive: \"Utilities for handling archive formatted files\",\n async: \"Utilities for helping with asynchronous tasks\",\n bytes: \"Helper functions to manipulate byte slices\",\n collections:\n \"Pure functions for handling common tasks around collection types\",\n crypto: \"Extensions to the web crypto APIs\",\n datetime:\n \"A helper function to parse date strings into `Date` objects and additional functions\",\n encoding: \"Helper modules for dealing with encoded data structures\",\n examples:\n \"Small scripts that demonstrate use of Deno and its standard modules\",\n flags: \"Command line arguments parser for Deno based on minimist\",\n fmt: \"Utilities for formatting strings for output\",\n fs: \"Helpers associated with file system tasks\",\n hash: \"**DEPRECATED** Use the Web Crypto APIs or `std/crypto` instead\",\n http: \"Wrapper utilities for Deno's built-in HTTP server\",\n io: \"Utility functions and classes to assist with IO tasks\",\n log: \"A logging framework\",\n mime: \"A utility for handling multi-part encoded bodies\",\n node: \"Utilities and polyfills for Node.js built-in modules\",\n path: \"Utility functions for manipulating file paths\",\n permissions: \"A utility for granting sets of permissions in one API call\",\n signal: \"A module used to capture and monitor OS signals\",\n streams:\n \"Utilities for working with Deno `Reader`/`Writer` interfaces and web streams\",\n testing: \"Utilities for making testing easier and consistent in Deno\",\n textproto: \"A port of Go's textproto\",\n uuid: \"Utilities for generating v1, v4, and v5 UUIDs\",\n wasi: \"Provides an implementation of the WebAssembly System Interface\",\n};\n\n/** Cache the response from api.deno.land. */\nfunction cacheResponse({ data: { results } }: ApiModuleSearchResponse) {\n for (const { name, description, star_count } of results) {\n packages.set(name, { name, description, stars: star_count });\n }\n}\n\n/** Invalidates the cache of version information if it older than 5 minutes. */\nfunction checkVersionsFreshness(): void {\n const now = Date.now();\n if (versionsInvalidated + 300_000 < now) {\n versionsInvalidated = now;\n versions.clear();\n }\n}\n\n/** Fetch the meta data for a specific package/module and version from the S3\n * bucket. */\nasync function fetchMeta(pkg: string, ver: string): Promise {\n if (!packageMeta.has(pkg)) {\n packageMeta.set(pkg, new Map());\n }\n const versionsMeta = packageMeta.get(pkg)!;\n const res = await fetch(`${S3_BUCKET}${pkg}/versions/${ver}/meta/meta.json`);\n if (res.status === 200) {\n versionsMeta.set(ver, await res.json());\n } else {\n versionsMeta.set(ver, {\n uploaded_at: \"\",\n directory_listing: [],\n upload_options: { type: \"\", repository: \"\", ref: \"\" },\n });\n }\n return versionsMeta.get(ver)!;\n}\n\n/** Fetch the version data for a specific package/module from the S3 bucket. */\nasync function fetchVersions(pkg: string): Promise {\n const res = await fetch(`${S3_BUCKET}${pkg}/meta/versions.json`);\n if (res.status === 200) {\n versions.set(pkg, await res.json());\n } else {\n versions.set(pkg, { latest: \"\", versions: [] });\n }\n return versions.get(pkg)!;\n}\n\n/** Fetch package data from api.deno.land for a specific package/module. */\nasync function fetchPackageData(pkg: string): Promise {\n const res = await fetch(`https://api.deno.land/modules/${pkg}`);\n if (res.status === 200) {\n const { data: { name, description, star_count: stars } }:\n ApiModuleResponse = await res.json();\n packages.set(pkg, {\n name,\n description,\n stars,\n });\n } else {\n packages.set(pkg, {\n name: pkg,\n description: \"\",\n stars: 0,\n });\n }\n return packages.get(pkg)!;\n}\n\n/** Lazily update the module list for searching with fuse every 2 minutes and\n * return a reference. */\nasync function getFuse(): Promise {\n const now = Date.now();\n if (fuseUpdated + 120_000 < now) {\n fuseUpdated = now;\n const res = await fetch(MODULE_LIST);\n if (res.status === 200) {\n fuse = new Fuse(await res.json(), { includeScore: true, distance: 10 });\n }\n }\n return fuse;\n}\n\n/** Get the initial package list to send to the client when no specific module\n * is being searched for. */\nasync function getInitialPackageList() {\n if (!initialList) {\n const res = await fetch(INITIAL_LIST);\n if (res.status !== 200) {\n throw new Error(\"bad api response\");\n }\n const json: ApiModuleSearchResponse = await res.json();\n cacheResponse(json);\n initialList = toItems(json);\n }\n return initialList;\n}\n\n/** Given a package, return its latest version. */\nasync function getLatestVersion(pkg: string): Promise {\n checkVersionsFreshness();\n const data = versions.get(pkg) ?? await fetchVersions(pkg);\n return data.latest;\n}\n\nfunction getMeta(pkg: string, ver: string): MetaJson | undefined {\n return packageMeta.get(pkg)?.get(ver);\n}\n\n/** When dealing with a path, try to preselect the most logical module for the\n * user. */\nfunction getPreselectPath(items: string[]): string | undefined {\n // preselect anything that appears to be a root file in order\n const preselect = [\n \"mod.ts\",\n \"mod.js\",\n \"main.ts\",\n \"main.js\",\n \"lib.ts\",\n \"lib.js\",\n \"index.ts\",\n \"index.mjs\",\n \"index.js\",\n ]\n .find((i) => items.includes(i));\n if (preselect) {\n return preselect;\n }\n // when navigating subdirs, then preselect the first thing we encounter that\n // appears to be an root file in the subdir\n return items.find((i) =>\n [\n \"/mod.ts\",\n \"/mod.js\",\n \"/main.ts\",\n \"/main.js\",\n \"/lib.ts\",\n \"/lib.js\",\n \"/index.ts\",\n \"/index.mjs\",\n \"/index.js\",\n ].find((s) => i.endsWith(s))\n );\n}\n\n/** Given a package and optionally the current path, return a set of items\n * that allows sub navigation of a directory structure. */\nfunction toFileItems(meta: MetaJson, currentPath = \"\"): string[] {\n let dirs: string[] = [];\n let items: string[] = [];\n for (const { path, type } of meta.directory_listing) {\n if (\n type === \"dir\" && path.startsWith(`/${currentPath}`) &&\n path !== (`/${currentPath}`) &&\n !path.match(/\\/[_.]/)\n ) {\n dirs.push(`${path.slice(1)}/`);\n } else if (\n path.startsWith(`/${currentPath}`) && path !== (`/${currentPath}`) &&\n !path.match(/\\/[_.]/) &&\n path.match(/\\.(jsx?|tsx?|mjs|cjs|mts|cts|json)$/i)\n ) {\n items.push(path.slice(1));\n }\n }\n dirs = dirs.filter((dir) => items.some((item) => item.startsWith(dir)));\n dirs = dirs.filter((dir) =>\n !dir.replace(currentPath, \"\").slice(0, -1).includes(\"/\")\n );\n items = items.filter((item) => !dirs.some((dir) => item.startsWith(dir)));\n return [...dirs, ...items];\n}\n\n/** Convert an API search response into a list of module/package names. */\nfunction toItems({ data: { results } }: ApiModuleSearchResponse) {\n return results.map(({ name }) => name);\n}\n\nfunction toPathDocs(\n pkg: string,\n ver: string,\n path: string,\n meta: MetaJson,\n): string {\n const matchPath = `/${path}`;\n const listing =\n meta.directory_listing.find(({ path }) => path === matchPath) ??\n { size: 0, type: \"file\", path: \"\" };\n const { size, type } = listing;\n return type === \"file\"\n ? `[docs](https://doc.deno.land/https://deno.land/x/${pkg}@${ver}/${path}) | [code](https://deno.land/x/${pkg}@${ver}/${path}) | size: ${\n prettyBytes(size)\n }\\n`\n : `[code](https://deno.land/x/${pkg}@${ver}/${path}) | size: ${\n prettyBytes(size)\n }`;\n}\n\nfunction toStdVersionDocs(\n ver: string,\n meta: MetaJson,\n): string {\n return `**Deno \\`std\\` library @ ${ver}**\\n\\nA collection of modules to assist with common tasks in Deno.\\n\\n[code](https://deno.land/std@${ver}) | published: _${\n twas(new Date(meta.uploaded_at))\n }_\\n\\n`;\n}\n\nfunction toStdPathDocs(ver: string, path: string, meta: MetaJson): string {\n const matchPath = `/${path}`;\n const listing =\n meta.directory_listing.find(({ path }) => path === matchPath) ??\n { size: 0, type: \"file\", path: \"\" };\n const { size, type } = listing;\n const [mod] = path && path.includes(\"/\") ? path.split(\"/\") : [path];\n const leading = mod in stdDescriptions\n ? `**${mod}**\\n\\n${stdDescriptions[mod] ?? \"\"}\\n\\n`\n : \"\";\n const body = type === \"file\"\n ? `[docs](https://doc.deno.land/https://deno.land/std@${ver}/${path}) | [code](https://deno.land/std@${ver}/${path}) | size: ${\n prettyBytes(size)\n }\\n`\n : `[code](https://deno.land/std@${ver}/${path}) | size: ${\n prettyBytes(size)\n }`;\n return `${leading}${body}`;\n}\n\nfunction toVersionDocs(\n pkgData: PackageData,\n ver: string,\n meta: MetaJson,\n): string {\n return `**${pkgData.name} @ ${ver}**\\n\\n${pkgData.description}\\n\\n[code](https://deno.land/x/${pkgData.name}@${ver}) | published: _${\n twas(new Date(meta.uploaded_at))\n }_${pkgData.stars ? ` | stars: _${pkgData.stars}_` : \"\"}\\n\\n`;\n}\n\n// /_api/details/x/:pkg\nasync function handlePackageDetails(\n match: URLPatternResult,\n): Promise {\n const { pkg } = match.pathname.groups;\n const pkgData = packages.get(pkg) ?? await fetchPackageData(pkg);\n const body = {\n kind: \"markdown\",\n value:\n `**${pkgData.name}**\\n\\n${pkgData.description}\\n\\n[code](https://deno.land/x/${pkg})${\n pkgData.stars ? ` | stars: _${pkgData.stars}_` : \"\"\n }\\n\\n`,\n };\n return Promise.resolve(\n new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_DAY,\n \"content-type\": \"application/json\",\n },\n }),\n );\n}\n\n// /_api/x/:pkg\nasync function handlePackages(match: URLPatternResult): Promise {\n const { pkg } = match.pathname.groups;\n if (!pkg) {\n return new Response(\n JSON.stringify({\n items: await getInitialPackageList(),\n isIncomplete: true,\n }),\n {\n headers: {\n \"cache-control\": MAX_AGE_1_HOUR,\n \"content-type\": \"application/json\",\n },\n },\n );\n } else {\n const fuse = await getFuse();\n const foundItems = fuse.search(pkg);\n const found: string[] = foundItems.map(({ item }: { item: string }) =>\n item\n );\n const items = found.slice(0, 100);\n const body = {\n items,\n isIncomplete: found.length > items.length,\n preselect: (foundItems[0].score === 0) ? foundItems[0].item : undefined,\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_HOUR,\n \"content-type\": \"application/json\",\n },\n });\n }\n}\n\n// /_api/x/:pkg/:ver/:path\nasync function handlePaths(match: URLPatternResult): Promise {\n let { pkg, ver, path } = match.pathname.groups;\n if (ver === \"_latest\") {\n ver = await getLatestVersion(pkg);\n }\n const meta = getMeta(pkg, ver) ?? await fetchMeta(pkg, ver);\n const items = toFileItems(meta, path);\n const body = {\n items,\n isIncomplete: true,\n preselect: getPreselectPath(items),\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\",\n },\n });\n}\n\n// /_api/x/:pkg/:ver\nasync function handleVersions(match: URLPatternResult): Promise {\n const { pkg, ver } = match.pathname.groups;\n checkVersionsFreshness();\n const versionInfo = versions.get(pkg) ?? await fetchVersions(pkg);\n const items = ver\n ? versionInfo.versions.filter((v) => v.startsWith(ver))\n : versionInfo.versions;\n const body = {\n items,\n isIncomplete: false,\n preselect: items.find((v) => v === versionInfo.latest),\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_HOUR,\n \"content-type\": \"application/json\",\n },\n });\n}\n\n// /_api/details/x/:pkg/:ver/:path\nasync function handlePathDetails(match: URLPatternResult): Promise {\n let { pkg, ver, path } = match.pathname.groups;\n if (ver === \"_latest\") {\n ver = await getLatestVersion(pkg);\n }\n const meta = getMeta(pkg, ver) ?? await fetchMeta(pkg, ver);\n const body = {\n kind: \"markdown\",\n value: toPathDocs(pkg, ver, path, meta),\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\",\n },\n });\n}\n\n// /_api/details/std/:ver\nasync function handleStdVersionDetails(\n match: URLPatternResult,\n): Promise {\n const { ver } = match.pathname.groups;\n const meta = getMeta(\"std\", ver) ?? await fetchMeta(\"std\", ver);\n const body = {\n kind: \"markdown\",\n value: toStdVersionDocs(ver, meta),\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\",\n },\n });\n}\n\n// /_api/details/std/:ver/:path\nasync function handleStdPathDetails(\n match: URLPatternResult,\n): Promise {\n let { ver, path } = match.pathname.groups;\n if (ver === \"_latest\") {\n ver = await getLatestVersion(\"std\");\n }\n const meta = getMeta(\"std\", ver) ?? await fetchMeta(\"std\", ver);\n const body = {\n kind: \"markdown\",\n value: toStdPathDocs(ver, path, meta),\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\",\n },\n });\n}\n\n// /_api/details/x/:pkg/:ver\nasync function handleVersionDetails(\n match: URLPatternResult,\n): Promise {\n const { pkg, ver } = match.pathname.groups;\n const pkgData = packages.get(pkg) ?? await fetchPackageData(pkg);\n const meta = getMeta(pkg, ver) ?? await fetchMeta(pkg, ver);\n const body = {\n kind: \"markdown\",\n value: toVersionDocs(pkgData, ver, meta),\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\",\n },\n });\n}\n\n/** Routes that get matched and delegated to sub handlers.*/\nconst patterns: [string, (match: URLPatternResult) => Promise][] = [\n [\"/_api/x/{:pkg}?\", handlePackages],\n [\"/_api/details/x/:pkg\", handlePackageDetails],\n [\"/_api/x/:pkg/{:ver}?\", handleVersions],\n [\"/_api/details/x/:pkg/:ver\", handleVersionDetails],\n [\"/_api/x/:pkg/:ver/:path*{/}?\", handlePaths],\n [\"/_api/details/x/:pkg/:ver/:path*{/}?\", handlePathDetails],\n\n [\"/_api/details/std/:ver\", handleStdVersionDetails],\n [\"/_api/details/std/:ver/:path*{/}?\", handleStdPathDetails],\n];\n\n/** Handle registry v2 API requests. */\nexport function handleApiRequest(url: URL): Promise {\n for (const [pattern, handler] of patterns) {\n const result = new URLPattern(pattern, url.toString()).exec(url);\n if (result) {\n try {\n return handler(result);\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"internal error\";\n return Promise.resolve(\n new Response(msg, { status: 500, statusText: \"InternalError\" }),\n );\n }\n }\n }\n return Promise.resolve(\n new Response(null, {\n status: 404,\n statusText: \"NotFound\",\n }),\n );\n}\n", - "transpiled": "/* Copyright 2021-2022 the Deno authors. All rights reserved. MIT license. */ // @deno-types https://deno.land/x/fuse@v6.4.1/dist/fuse.d.ts\nimport { default as Fuse } from \"https://deno.land/x/fuse@v6.4.1/dist/fuse.esm.js\";\nimport { prettyBytes } from \"https://deno.land/x/pretty_bytes@v1.0.5/mod.ts\";\nimport twas from \"https://esm.sh/twas@2.1.2\";\nimport { S3_BUCKET } from \"./registry.ts\";\nconst MODULE_LIST = \"https://api.deno.land/modules?simple=1\";\nconst INITIAL_LIST = \"https://api.deno.land/modules?limit=50&sort=stars\";\nconst MAX_AGE_1_HOUR = \"max-age=3600\";\nconst MAX_AGE_1_DAY = \"max-age=86400\";\nconst IMMUTABLE = \"max-age=2628000, immutable\";\nlet fuse = new Fuse([], {\n includeScore: true,\n distance: 10\n});\n/** If the index searching hasn't been updated in > 120 seconds, it will be\n * refreshed before processing the next request, meaning the index of packages\n * will be kept fresh. */ let fuseUpdated = 0;\n/** A cache of all the package data retrieved from api.deno.land.\n *\n * Since this data only contains the description and the star count, which\n * are likely to change slowly, and don't materially impact the responses, the\n * cached values will be reset when the worker is restarted, which is likely\n * sufficient invalidation. */ const packages = new Map();\n/** The initial list of packages displayed when there is no specific package\n * being searched for. Currently this will be the top 50 packages/modules in\n * the registry order by star count. */ let initialList;\n/** A cache of all the package data retrieved from the S3 bucket. */ const packageMeta = new Map();\n/** A cache of a modules version data retrieved from the S3 bucket. */ const versions = new Map();\n/** We will cache versions of packages/modules for up to 5 minutes before\n * considering them state, and clearing them out. */ let versionsInvalidated = Date.now();\n/** Descriptions of the packages/modules that are in `std`.\n *\n * TODO(@kitsonk): move to `std` as a JSON file which is retrieved. */ const stdDescriptions = {\n archive: \"Utilities for handling archive formatted files\",\n async: \"Utilities for helping with asynchronous tasks\",\n bytes: \"Helper functions to manipulate byte slices\",\n collections: \"Pure functions for handling common tasks around collection types\",\n crypto: \"Extensions to the web crypto APIs\",\n datetime: \"A helper function to parse date strings into `Date` objects and additional functions\",\n encoding: \"Helper modules for dealing with encoded data structures\",\n examples: \"Small scripts that demonstrate use of Deno and its standard modules\",\n flags: \"Command line arguments parser for Deno based on minimist\",\n fmt: \"Utilities for formatting strings for output\",\n fs: \"Helpers associated with file system tasks\",\n hash: \"**DEPRECATED** Use the Web Crypto APIs or `std/crypto` instead\",\n http: \"Wrapper utilities for Deno's built-in HTTP server\",\n io: \"Utility functions and classes to assist with IO tasks\",\n log: \"A logging framework\",\n mime: \"A utility for handling multi-part encoded bodies\",\n node: \"Utilities and polyfills for Node.js built-in modules\",\n path: \"Utility functions for manipulating file paths\",\n permissions: \"A utility for granting sets of permissions in one API call\",\n signal: \"A module used to capture and monitor OS signals\",\n streams: \"Utilities for working with Deno `Reader`/`Writer` interfaces and web streams\",\n testing: \"Utilities for making testing easier and consistent in Deno\",\n textproto: \"A port of Go's textproto\",\n uuid: \"Utilities for generating v1, v4, and v5 UUIDs\",\n wasi: \"Provides an implementation of the WebAssembly System Interface\"\n};\n/** Cache the response from api.deno.land. */ function cacheResponse({ data: { results } }) {\n for (const { name , description , star_count } of results){\n packages.set(name, {\n name,\n description,\n stars: star_count\n });\n }\n}\n/** Invalidates the cache of version information if it older than 5 minutes. */ function checkVersionsFreshness() {\n const now = Date.now();\n if (versionsInvalidated + 300000 < now) {\n versionsInvalidated = now;\n versions.clear();\n }\n}\n/** Fetch the meta data for a specific package/module and version from the S3\n * bucket. */ async function fetchMeta(pkg, ver) {\n if (!packageMeta.has(pkg)) {\n packageMeta.set(pkg, new Map());\n }\n const versionsMeta = packageMeta.get(pkg);\n const res = await fetch(`${S3_BUCKET}${pkg}/versions/${ver}/meta/meta.json`);\n if (res.status === 200) {\n versionsMeta.set(ver, await res.json());\n } else {\n versionsMeta.set(ver, {\n uploaded_at: \"\",\n directory_listing: [],\n upload_options: {\n type: \"\",\n repository: \"\",\n ref: \"\"\n }\n });\n }\n return versionsMeta.get(ver);\n}\n/** Fetch the version data for a specific package/module from the S3 bucket. */ async function fetchVersions(pkg) {\n const res = await fetch(`${S3_BUCKET}${pkg}/meta/versions.json`);\n if (res.status === 200) {\n versions.set(pkg, await res.json());\n } else {\n versions.set(pkg, {\n latest: \"\",\n versions: []\n });\n }\n return versions.get(pkg);\n}\n/** Fetch package data from api.deno.land for a specific package/module. */ async function fetchPackageData(pkg) {\n const res = await fetch(`https://api.deno.land/modules/${pkg}`);\n if (res.status === 200) {\n const { data: { name , description , star_count: stars } } = await res.json();\n packages.set(pkg, {\n name,\n description,\n stars\n });\n } else {\n packages.set(pkg, {\n name: pkg,\n description: \"\",\n stars: 0\n });\n }\n return packages.get(pkg);\n}\n/** Lazily update the module list for searching with fuse every 2 minutes and\n * return a reference. */ async function getFuse() {\n const now = Date.now();\n if (fuseUpdated + 120000 < now) {\n fuseUpdated = now;\n const res = await fetch(MODULE_LIST);\n if (res.status === 200) {\n fuse = new Fuse(await res.json(), {\n includeScore: true,\n distance: 10\n });\n }\n }\n return fuse;\n}\n/** Get the initial package list to send to the client when no specific module\n * is being searched for. */ async function getInitialPackageList() {\n if (!initialList) {\n const res = await fetch(INITIAL_LIST);\n if (res.status !== 200) {\n throw new Error(\"bad api response\");\n }\n const json = await res.json();\n cacheResponse(json);\n initialList = toItems(json);\n }\n return initialList;\n}\n/** Given a package, return its latest version. */ async function getLatestVersion(pkg) {\n checkVersionsFreshness();\n const data = versions.get(pkg) ?? await fetchVersions(pkg);\n return data.latest;\n}\nfunction getMeta(pkg, ver) {\n return packageMeta.get(pkg)?.get(ver);\n}\n/** When dealing with a path, try to preselect the most logical module for the\n * user. */ function getPreselectPath(items) {\n // preselect anything that appears to be a root file in order\n const preselect = [\n \"mod.ts\",\n \"mod.js\",\n \"main.ts\",\n \"main.js\",\n \"lib.ts\",\n \"lib.js\",\n \"index.ts\",\n \"index.mjs\",\n \"index.js\", \n ].find((i)=>items.includes(i)\n );\n if (preselect) {\n return preselect;\n }\n // when navigating subdirs, then preselect the first thing we encounter that\n // appears to be an root file in the subdir\n return items.find((i)=>[\n \"/mod.ts\",\n \"/mod.js\",\n \"/main.ts\",\n \"/main.js\",\n \"/lib.ts\",\n \"/lib.js\",\n \"/index.ts\",\n \"/index.mjs\",\n \"/index.js\", \n ].find((s)=>i.endsWith(s)\n )\n );\n}\n/** Given a package and optionally the current path, return a set of items\n * that allows sub navigation of a directory structure. */ function toFileItems(meta, currentPath = \"\") {\n let dirs = [];\n let items = [];\n for (const { path , type } of meta.directory_listing){\n if (type === \"dir\" && path.startsWith(`/${currentPath}`) && path !== `/${currentPath}` && !path.match(/\\/[_.]/)) {\n dirs.push(`${path.slice(1)}/`);\n } else if (path.startsWith(`/${currentPath}`) && path !== `/${currentPath}` && !path.match(/\\/[_.]/) && path.match(/\\.(jsx?|tsx?|mjs|cjs|mts|cts|json)$/i)) {\n items.push(path.slice(1));\n }\n }\n dirs = dirs.filter((dir)=>items.some((item)=>item.startsWith(dir)\n )\n );\n dirs = dirs.filter((dir)=>!dir.replace(currentPath, \"\").slice(0, -1).includes(\"/\")\n );\n items = items.filter((item)=>!dirs.some((dir)=>item.startsWith(dir)\n )\n );\n return [\n ...dirs,\n ...items\n ];\n}\n/** Convert an API search response into a list of module/package names. */ function toItems({ data: { results } }) {\n return results.map(({ name })=>name\n );\n}\nfunction toPathDocs(pkg, ver, path, meta) {\n const matchPath = `/${path}`;\n const listing = meta.directory_listing.find(({ path })=>path === matchPath\n ) ?? {\n size: 0,\n type: \"file\",\n path: \"\"\n };\n const { size , type } = listing;\n return type === \"file\" ? `[docs](https://doc.deno.land/https://deno.land/x/${pkg}@${ver}/${path}) | [code](https://deno.land/x/${pkg}@${ver}/${path}) | size: ${prettyBytes(size)}\\n` : `[code](https://deno.land/x/${pkg}@${ver}/${path}) | size: ${prettyBytes(size)}`;\n}\nfunction toStdVersionDocs(ver, meta) {\n return `**Deno \\`std\\` library @ ${ver}**\\n\\nA collection of modules to assist with common tasks in Deno.\\n\\n[code](https://deno.land/std@${ver}) | published: _${twas(new Date(meta.uploaded_at))}_\\n\\n`;\n}\nfunction toStdPathDocs(ver, path, meta) {\n const matchPath = `/${path}`;\n const listing = meta.directory_listing.find(({ path })=>path === matchPath\n ) ?? {\n size: 0,\n type: \"file\",\n path: \"\"\n };\n const { size , type } = listing;\n const [mod] = path && path.includes(\"/\") ? path.split(\"/\") : [\n path\n ];\n const leading = mod in stdDescriptions ? `**${mod}**\\n\\n${stdDescriptions[mod] ?? \"\"}\\n\\n` : \"\";\n const body = type === \"file\" ? `[docs](https://doc.deno.land/https://deno.land/std@${ver}/${path}) | [code](https://deno.land/std@${ver}/${path}) | size: ${prettyBytes(size)}\\n` : `[code](https://deno.land/std@${ver}/${path}) | size: ${prettyBytes(size)}`;\n return `${leading}${body}`;\n}\nfunction toVersionDocs(pkgData, ver, meta) {\n return `**${pkgData.name} @ ${ver}**\\n\\n${pkgData.description}\\n\\n[code](https://deno.land/x/${pkgData.name}@${ver}) | published: _${twas(new Date(meta.uploaded_at))}_${pkgData.stars ? ` | stars: _${pkgData.stars}_` : \"\"}\\n\\n`;\n}\n// /_api/details/x/:pkg\nasync function handlePackageDetails(match) {\n const { pkg } = match.pathname.groups;\n const pkgData = packages.get(pkg) ?? await fetchPackageData(pkg);\n const body = {\n kind: \"markdown\",\n value: `**${pkgData.name}**\\n\\n${pkgData.description}\\n\\n[code](https://deno.land/x/${pkg})${pkgData.stars ? ` | stars: _${pkgData.stars}_` : \"\"}\\n\\n`\n };\n return Promise.resolve(new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_DAY,\n \"content-type\": \"application/json\"\n }\n }));\n}\n// /_api/x/:pkg\nasync function handlePackages(match) {\n const { pkg } = match.pathname.groups;\n if (!pkg) {\n return new Response(JSON.stringify({\n items: await getInitialPackageList(),\n isIncomplete: true\n }), {\n headers: {\n \"cache-control\": MAX_AGE_1_HOUR,\n \"content-type\": \"application/json\"\n }\n });\n } else {\n const fuse = await getFuse();\n const foundItems = fuse.search(pkg);\n const found = foundItems.map(({ item })=>item\n );\n const items = found.slice(0, 100);\n const body = {\n items,\n isIncomplete: found.length > items.length,\n preselect: foundItems[0].score === 0 ? foundItems[0].item : undefined\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_HOUR,\n \"content-type\": \"application/json\"\n }\n });\n }\n}\n// /_api/x/:pkg/:ver/:path\nasync function handlePaths(match) {\n let { pkg , ver , path } = match.pathname.groups;\n if (ver === \"_latest\") {\n ver = await getLatestVersion(pkg);\n }\n const meta = getMeta(pkg, ver) ?? await fetchMeta(pkg, ver);\n const items = toFileItems(meta, path);\n const body = {\n items,\n isIncomplete: true,\n preselect: getPreselectPath(items)\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\"\n }\n });\n}\n// /_api/x/:pkg/:ver\nasync function handleVersions(match) {\n const { pkg , ver } = match.pathname.groups;\n checkVersionsFreshness();\n const versionInfo = versions.get(pkg) ?? await fetchVersions(pkg);\n const items = ver ? versionInfo.versions.filter((v)=>v.startsWith(ver)\n ) : versionInfo.versions;\n const body = {\n items,\n isIncomplete: false,\n preselect: items.find((v)=>v === versionInfo.latest\n )\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_HOUR,\n \"content-type\": \"application/json\"\n }\n });\n}\n// /_api/details/x/:pkg/:ver/:path\nasync function handlePathDetails(match) {\n let { pkg , ver , path } = match.pathname.groups;\n if (ver === \"_latest\") {\n ver = await getLatestVersion(pkg);\n }\n const meta = getMeta(pkg, ver) ?? await fetchMeta(pkg, ver);\n const body = {\n kind: \"markdown\",\n value: toPathDocs(pkg, ver, path, meta)\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\"\n }\n });\n}\n// /_api/details/std/:ver\nasync function handleStdVersionDetails(match) {\n const { ver } = match.pathname.groups;\n const meta = getMeta(\"std\", ver) ?? await fetchMeta(\"std\", ver);\n const body = {\n kind: \"markdown\",\n value: toStdVersionDocs(ver, meta)\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\"\n }\n });\n}\n// /_api/details/std/:ver/:path\nasync function handleStdPathDetails(match) {\n let { ver , path } = match.pathname.groups;\n if (ver === \"_latest\") {\n ver = await getLatestVersion(\"std\");\n }\n const meta = getMeta(\"std\", ver) ?? await fetchMeta(\"std\", ver);\n const body = {\n kind: \"markdown\",\n value: toStdPathDocs(ver, path, meta)\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\"\n }\n });\n}\n// /_api/details/x/:pkg/:ver\nasync function handleVersionDetails(match) {\n const { pkg , ver } = match.pathname.groups;\n const pkgData = packages.get(pkg) ?? await fetchPackageData(pkg);\n const meta = getMeta(pkg, ver) ?? await fetchMeta(pkg, ver);\n const body = {\n kind: \"markdown\",\n value: toVersionDocs(pkgData, ver, meta)\n };\n return new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": IMMUTABLE,\n \"content-type\": \"application/json\"\n }\n });\n}\n/** Routes that get matched and delegated to sub handlers.*/ const patterns = [\n [\n \"/_api/x/{:pkg}?\",\n handlePackages\n ],\n [\n \"/_api/details/x/:pkg\",\n handlePackageDetails\n ],\n [\n \"/_api/x/:pkg/{:ver}?\",\n handleVersions\n ],\n [\n \"/_api/details/x/:pkg/:ver\",\n handleVersionDetails\n ],\n [\n \"/_api/x/:pkg/:ver/:path*{/}?\",\n handlePaths\n ],\n [\n \"/_api/details/x/:pkg/:ver/:path*{/}?\",\n handlePathDetails\n ],\n [\n \"/_api/details/std/:ver\",\n handleStdVersionDetails\n ],\n [\n \"/_api/details/std/:ver/:path*{/}?\",\n handleStdPathDetails\n ], \n];\n/** Handle registry v2 API requests. */ export function handleApiRequest(url) {\n for (const [pattern, handler] of patterns){\n const result = new URLPattern(pattern, url.toString()).exec(url);\n if (result) {\n try {\n return handler(result);\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"internal error\";\n return Promise.resolve(new Response(msg, {\n status: 500,\n statusText: \"InternalError\"\n }));\n }\n }\n }\n return Promise.resolve(new Response(null, {\n status: 404,\n statusText: \"NotFound\"\n }));\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxmaWxlOi8vL3NyYy93b3JrZXIvc3VnZ2VzdGlvbnMudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEVBQTZFLEFBQTdFLHlFQUE2RSxBQUE3RSxFQUE2RSxDQUU3RSxFQUE2RCxBQUE3RCwyREFBNkQ7QUFDN0QsTUFBTSxHQUFHLE9BQU8sSUFBSSxJQUFJLFFBQVEsQ0FBa0Q7QUFDbEYsTUFBTSxHQUFHLFdBQVcsUUFBUSxDQUFnRDtBQUM1RSxNQUFNLENBQUMsSUFBSSxNQUFNLENBQTJCO0FBRTVDLE1BQU0sR0FBRyxTQUFTLFFBQVEsQ0FBZTtBQTJDekMsS0FBSyxDQUFDLFdBQVcsR0FBRyxDQUF3QztBQUM1RCxLQUFLLENBQUMsWUFBWSxHQUFHLENBQW1EO0FBQ3hFLEtBQUssQ0FBQyxjQUFjLEdBQUcsQ0FBYztBQUNyQyxLQUFLLENBQUMsYUFBYSxHQUFHLENBQWU7QUFDckMsS0FBSyxDQUFDLFNBQVMsR0FBRyxDQUE0QjtBQUU5QyxHQUFHLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUFDLFlBQVksRUFBRSxJQUFJO0lBQUUsUUFBUSxFQUFFLEVBQUU7QUFBQyxDQUFDO0FBQzVELEVBRXlCLEFBRnpCOzt1QkFFeUIsQUFGekIsRUFFeUIsQ0FDekIsR0FBRyxDQUFDLFdBQVcsR0FBRyxDQUFDO0FBRW5CLEVBSzhCLEFBTDlCOzs7Ozs0QkFLOEIsQUFMOUIsRUFLOEIsQ0FDOUIsS0FBSyxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsR0FBRztBQUN4QixFQUV1QyxBQUZ2Qzs7cUNBRXVDLEFBRnZDLEVBRXVDLENBQ3ZDLEdBQUcsQ0FBQyxXQUFXO0FBQ2YsRUFBb0UsQUFBcEUsZ0VBQW9FLEFBQXBFLEVBQW9FLENBQ3BFLEtBQUssQ0FBQyxXQUFXLEdBQUcsR0FBRyxDQUFDLEdBQUc7QUFDM0IsRUFBc0UsQUFBdEUsa0VBQXNFLEFBQXRFLEVBQXNFLENBQ3RFLEtBQUssQ0FBQyxR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", - "content_type": null, - "deps": [ - "https://deno.land/x/fuse@v6.4.1/dist/fuse.esm.js", - "https://deno.land/x/pretty_bytes@v1.0.5/mod.ts", - "https://esm.sh/twas@2.1.2", - "file:///src/worker/registry.ts" - ] - } - }, - "file:///src/worker/main.ts": { - "Source": { - "source": "#!/usr/bin/env -S deno run --allow-read=. --allow-net --allow-env\n/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */\n\nimport { handleRequest, withLog } from \"./handler.ts\";\nimport { listenAndServe } from \"https://deno.land/std@0.108.0/http/server.ts\";\n\nconst handler = withLog(handleRequest);\n\nconsole.log(\"The server is available at http://localhost:8081\");\nlistenAndServe(\":8081\", handler);\n", - "transpiled": "#!/usr/bin/env -S deno run --allow-read=. --allow-net --allow-env\n/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */ import { handleRequest, withLog } from \"./handler.ts\";\nimport { listenAndServe } from \"https://deno.land/std@0.108.0/http/server.ts\";\nconst handler = withLog(handleRequest);\nconsole.log(\"The server is available at http://localhost:8081\");\nlistenAndServe(\":8081\", handler);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxmaWxlOi8vL3NyYy93b3JrZXIvbWFpbi50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLEVBQXdFLEFBQXhFLG9FQUF3RSxBQUF4RSxFQUF3RSxDQUV4RSxNQUFNLEdBQUcsYUFBYSxFQUFFLE9BQU8sUUFBUSxDQUFjO0FBQ3JELE1BQU0sR0FBRyxjQUFjLFFBQVEsQ0FBOEM7QUFFN0UsS0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsYUFBYTtBQUVyQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQWtEO0FBQzlELGNBQWMsQ0FBQyxDQUFPLFFBQUUsT0FBTyJ9", - "content_type": null, - "deps": [ - "file:///src/worker/handler.ts", - "https://deno.land/std@0.108.0/http/server.ts" - ] - } - }, - "https://deno.land/std@0.120.0/fmt/colors.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n// A module to print ANSI terminal colors. Inspired by chalk, kleur, and colors\n// on npm.\n//\n\n/**\n * ```ts\n * import { bgBlue, red, bold } from \"https://deno.land/std@$STD_VERSION/fmt/colors.ts\";\n * console.log(bgBlue(red(bold(\"Hello world!\"))));\n * ```\n *\n * This module supports `NO_COLOR` environmental variable disabling any coloring\n * if `NO_COLOR` is set.\n *\n * @module\n */\n// This module is browser compatible.\n\n// deno-lint-ignore no-explicit-any\nconst { Deno } = globalThis as any;\nconst noColor = typeof Deno?.noColor === \"boolean\"\n ? Deno.noColor as boolean\n : true;\n\ninterface Code {\n open: string;\n close: string;\n regexp: RegExp;\n}\n\n/** RGB 8-bits per channel. Each in range `0->255` or `0x00->0xff` */\ninterface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nlet enabled = !noColor;\n\n/**\n * Set changing text color to enabled or disabled\n * @param value\n */\nexport function setColorEnabled(value: boolean): void {\n if (noColor) {\n return;\n }\n\n enabled = value;\n}\n\n/** Get whether text color change is enabled or disabled. */\nexport function getColorEnabled(): boolean {\n return enabled;\n}\n\n/**\n * Builds color code\n * @param open\n * @param close\n */\nfunction code(open: number[], close: number): Code {\n return {\n open: `\\x1b[${open.join(\";\")}m`,\n close: `\\x1b[${close}m`,\n regexp: new RegExp(`\\\\x1b\\\\[${close}m`, \"g\"),\n };\n}\n\n/**\n * Applies color and background based on color code and its associated text\n * @param str text to apply color settings to\n * @param code color code to apply\n */\nfunction run(str: string, code: Code): string {\n return enabled\n ? `${code.open}${str.replace(code.regexp, code.open)}${code.close}`\n : str;\n}\n\n/**\n * Reset the text modified\n * @param str text to reset\n */\nexport function reset(str: string): string {\n return run(str, code([0], 0));\n}\n\n/**\n * Make the text bold.\n * @param str text to make bold\n */\nexport function bold(str: string): string {\n return run(str, code([1], 22));\n}\n\n/**\n * The text emits only a small amount of light.\n * @param str text to dim\n */\nexport function dim(str: string): string {\n return run(str, code([2], 22));\n}\n\n/**\n * Make the text italic.\n * @param str text to make italic\n */\nexport function italic(str: string): string {\n return run(str, code([3], 23));\n}\n\n/**\n * Make the text underline.\n * @param str text to underline\n */\nexport function underline(str: string): string {\n return run(str, code([4], 24));\n}\n\n/**\n * Invert background color and text color.\n * @param str text to invert its color\n */\nexport function inverse(str: string): string {\n return run(str, code([7], 27));\n}\n\n/**\n * Make the text hidden.\n * @param str text to hide\n */\nexport function hidden(str: string): string {\n return run(str, code([8], 28));\n}\n\n/**\n * Put horizontal line through the center of the text.\n * @param str text to strike through\n */\nexport function strikethrough(str: string): string {\n return run(str, code([9], 29));\n}\n\n/**\n * Set text color to black.\n * @param str text to make black\n */\nexport function black(str: string): string {\n return run(str, code([30], 39));\n}\n\n/**\n * Set text color to red.\n * @param str text to make red\n */\nexport function red(str: string): string {\n return run(str, code([31], 39));\n}\n\n/**\n * Set text color to green.\n * @param str text to make green\n */\nexport function green(str: string): string {\n return run(str, code([32], 39));\n}\n\n/**\n * Set text color to yellow.\n * @param str text to make yellow\n */\nexport function yellow(str: string): string {\n return run(str, code([33], 39));\n}\n\n/**\n * Set text color to blue.\n * @param str text to make blue\n */\nexport function blue(str: string): string {\n return run(str, code([34], 39));\n}\n\n/**\n * Set text color to magenta.\n * @param str text to make magenta\n */\nexport function magenta(str: string): string {\n return run(str, code([35], 39));\n}\n\n/**\n * Set text color to cyan.\n * @param str text to make cyan\n */\nexport function cyan(str: string): string {\n return run(str, code([36], 39));\n}\n\n/**\n * Set text color to white.\n * @param str text to make white\n */\nexport function white(str: string): string {\n return run(str, code([37], 39));\n}\n\n/**\n * Set text color to gray.\n * @param str text to make gray\n */\nexport function gray(str: string): string {\n return brightBlack(str);\n}\n\n/**\n * Set text color to bright black.\n * @param str text to make bright-black\n */\nexport function brightBlack(str: string): string {\n return run(str, code([90], 39));\n}\n\n/**\n * Set text color to bright red.\n * @param str text to make bright-red\n */\nexport function brightRed(str: string): string {\n return run(str, code([91], 39));\n}\n\n/**\n * Set text color to bright green.\n * @param str text to make bright-green\n */\nexport function brightGreen(str: string): string {\n return run(str, code([92], 39));\n}\n\n/**\n * Set text color to bright yellow.\n * @param str text to make bright-yellow\n */\nexport function brightYellow(str: string): string {\n return run(str, code([93], 39));\n}\n\n/**\n * Set text color to bright blue.\n * @param str text to make bright-blue\n */\nexport function brightBlue(str: string): string {\n return run(str, code([94], 39));\n}\n\n/**\n * Set text color to bright magenta.\n * @param str text to make bright-magenta\n */\nexport function brightMagenta(str: string): string {\n return run(str, code([95], 39));\n}\n\n/**\n * Set text color to bright cyan.\n * @param str text to make bright-cyan\n */\nexport function brightCyan(str: string): string {\n return run(str, code([96], 39));\n}\n\n/**\n * Set text color to bright white.\n * @param str text to make bright-white\n */\nexport function brightWhite(str: string): string {\n return run(str, code([97], 39));\n}\n\n/**\n * Set background color to black.\n * @param str text to make its background black\n */\nexport function bgBlack(str: string): string {\n return run(str, code([40], 49));\n}\n\n/**\n * Set background color to red.\n * @param str text to make its background red\n */\nexport function bgRed(str: string): string {\n return run(str, code([41], 49));\n}\n\n/**\n * Set background color to green.\n * @param str text to make its background green\n */\nexport function bgGreen(str: string): string {\n return run(str, code([42], 49));\n}\n\n/**\n * Set background color to yellow.\n * @param str text to make its background yellow\n */\nexport function bgYellow(str: string): string {\n return run(str, code([43], 49));\n}\n\n/**\n * Set background color to blue.\n * @param str text to make its background blue\n */\nexport function bgBlue(str: string): string {\n return run(str, code([44], 49));\n}\n\n/**\n * Set background color to magenta.\n * @param str text to make its background magenta\n */\nexport function bgMagenta(str: string): string {\n return run(str, code([45], 49));\n}\n\n/**\n * Set background color to cyan.\n * @param str text to make its background cyan\n */\nexport function bgCyan(str: string): string {\n return run(str, code([46], 49));\n}\n\n/**\n * Set background color to white.\n * @param str text to make its background white\n */\nexport function bgWhite(str: string): string {\n return run(str, code([47], 49));\n}\n\n/**\n * Set background color to bright black.\n * @param str text to make its background bright-black\n */\nexport function bgBrightBlack(str: string): string {\n return run(str, code([100], 49));\n}\n\n/**\n * Set background color to bright red.\n * @param str text to make its background bright-red\n */\nexport function bgBrightRed(str: string): string {\n return run(str, code([101], 49));\n}\n\n/**\n * Set background color to bright green.\n * @param str text to make its background bright-green\n */\nexport function bgBrightGreen(str: string): string {\n return run(str, code([102], 49));\n}\n\n/**\n * Set background color to bright yellow.\n * @param str text to make its background bright-yellow\n */\nexport function bgBrightYellow(str: string): string {\n return run(str, code([103], 49));\n}\n\n/**\n * Set background color to bright blue.\n * @param str text to make its background bright-blue\n */\nexport function bgBrightBlue(str: string): string {\n return run(str, code([104], 49));\n}\n\n/**\n * Set background color to bright magenta.\n * @param str text to make its background bright-magenta\n */\nexport function bgBrightMagenta(str: string): string {\n return run(str, code([105], 49));\n}\n\n/**\n * Set background color to bright cyan.\n * @param str text to make its background bright-cyan\n */\nexport function bgBrightCyan(str: string): string {\n return run(str, code([106], 49));\n}\n\n/**\n * Set background color to bright white.\n * @param str text to make its background bright-white\n */\nexport function bgBrightWhite(str: string): string {\n return run(str, code([107], 49));\n}\n\n/* Special Color Sequences */\n\n/**\n * Clam and truncate color codes\n * @param n\n * @param max number to truncate to\n * @param min number to truncate from\n */\nfunction clampAndTruncate(n: number, max = 255, min = 0): number {\n return Math.trunc(Math.max(Math.min(n, max), min));\n}\n\n/**\n * Set text color using paletted 8bit colors.\n * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit\n * @param str text color to apply paletted 8bit colors to\n * @param color code\n */\nexport function rgb8(str: string, color: number): string {\n return run(str, code([38, 5, clampAndTruncate(color)], 39));\n}\n\n/**\n * Set background color using paletted 8bit colors.\n * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit\n * @param str text color to apply paletted 8bit background colors to\n * @param color code\n */\nexport function bgRgb8(str: string, color: number): string {\n return run(str, code([48, 5, clampAndTruncate(color)], 49));\n}\n\n/**\n * Set text color using 24bit rgb.\n * `color` can be a number in range `0x000000` to `0xffffff` or\n * an `Rgb`.\n *\n * To produce the color magenta:\n *\n * ```ts\n * import { rgb24 } from \"./colors.ts\";\n * rgb24(\"foo\", 0xff00ff);\n * rgb24(\"foo\", {r: 255, g: 0, b: 255});\n * ```\n * @param str text color to apply 24bit rgb to\n * @param color code\n */\nexport function rgb24(str: string, color: number | Rgb): string {\n if (typeof color === \"number\") {\n return run(\n str,\n code(\n [38, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff],\n 39,\n ),\n );\n }\n return run(\n str,\n code(\n [\n 38,\n 2,\n clampAndTruncate(color.r),\n clampAndTruncate(color.g),\n clampAndTruncate(color.b),\n ],\n 39,\n ),\n );\n}\n\n/**\n * Set background color using 24bit rgb.\n * `color` can be a number in range `0x000000` to `0xffffff` or\n * an `Rgb`.\n *\n * To produce the color magenta:\n *\n * ```ts\n * import { bgRgb24 } from \"./colors.ts\";\n * bgRgb24(\"foo\", 0xff00ff);\n * bgRgb24(\"foo\", {r: 255, g: 0, b: 255});\n * ```\n * @param str text color to apply 24bit rgb to\n * @param color code\n */\nexport function bgRgb24(str: string, color: number | Rgb): string {\n if (typeof color === \"number\") {\n return run(\n str,\n code(\n [48, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff],\n 49,\n ),\n );\n }\n return run(\n str,\n code(\n [\n 48,\n 2,\n clampAndTruncate(color.r),\n clampAndTruncate(color.g),\n clampAndTruncate(color.b),\n ],\n 49,\n ),\n );\n}\n\n// https://github.com/chalk/ansi-regex/blob/2b56fb0c7a07108e5b54241e8faec160d393aedb/index.js\nconst ANSI_PATTERN = new RegExp(\n [\n \"[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:[a-zA-Z\\\\d]*(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)\",\n \"(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~]))\",\n ].join(\"|\"),\n \"g\",\n);\n\n/**\n * Remove ANSI escape codes from the string.\n * @param string to remove ANSI escape codes from\n */\nexport function stripColor(string: string): string {\n return string.replace(ANSI_PATTERN, \"\");\n}\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n// A module to print ANSI terminal colors. Inspired by chalk, kleur, and colors\n// on npm.\n//\n/**\n * ```ts\n * import { bgBlue, red, bold } from \"https://deno.land/std@$STD_VERSION/fmt/colors.ts\";\n * console.log(bgBlue(red(bold(\"Hello world!\"))));\n * ```\n *\n * This module supports `NO_COLOR` environmental variable disabling any coloring\n * if `NO_COLOR` is set.\n *\n * @module\n */ // This module is browser compatible.\n// deno-lint-ignore no-explicit-any\nconst { Deno } = globalThis;\nconst noColor = typeof Deno?.noColor === \"boolean\" ? Deno.noColor : true;\nlet enabled = !noColor;\n/**\n * Set changing text color to enabled or disabled\n * @param value\n */ export function setColorEnabled(value) {\n if (noColor) {\n return;\n }\n enabled = value;\n}\n/** Get whether text color change is enabled or disabled. */ export function getColorEnabled() {\n return enabled;\n}\n/**\n * Builds color code\n * @param open\n * @param close\n */ function code(open, close) {\n return {\n open: `\\x1b[${open.join(\";\")}m`,\n close: `\\x1b[${close}m`,\n regexp: new RegExp(`\\\\x1b\\\\[${close}m`, \"g\")\n };\n}\n/**\n * Applies color and background based on color code and its associated text\n * @param str text to apply color settings to\n * @param code color code to apply\n */ function run(str, code) {\n return enabled ? `${code.open}${str.replace(code.regexp, code.open)}${code.close}` : str;\n}\n/**\n * Reset the text modified\n * @param str text to reset\n */ export function reset(str) {\n return run(str, code([\n 0\n ], 0));\n}\n/**\n * Make the text bold.\n * @param str text to make bold\n */ export function bold(str) {\n return run(str, code([\n 1\n ], 22));\n}\n/**\n * The text emits only a small amount of light.\n * @param str text to dim\n */ export function dim(str) {\n return run(str, code([\n 2\n ], 22));\n}\n/**\n * Make the text italic.\n * @param str text to make italic\n */ export function italic(str) {\n return run(str, code([\n 3\n ], 23));\n}\n/**\n * Make the text underline.\n * @param str text to underline\n */ export function underline(str) {\n return run(str, code([\n 4\n ], 24));\n}\n/**\n * Invert background color and text color.\n * @param str text to invert its color\n */ export function inverse(str) {\n return run(str, code([\n 7\n ], 27));\n}\n/**\n * Make the text hidden.\n * @param str text to hide\n */ export function hidden(str) {\n return run(str, code([\n 8\n ], 28));\n}\n/**\n * Put horizontal line through the center of the text.\n * @param str text to strike through\n */ export function strikethrough(str) {\n return run(str, code([\n 9\n ], 29));\n}\n/**\n * Set text color to black.\n * @param str text to make black\n */ export function black(str) {\n return run(str, code([\n 30\n ], 39));\n}\n/**\n * Set text color to red.\n * @param str text to make red\n */ export function red(str) {\n return run(str, code([\n 31\n ], 39));\n}\n/**\n * Set text color to green.\n * @param str text to make green\n */ export function green(str) {\n return run(str, code([\n 32\n ], 39));\n}\n/**\n * Set text color to yellow.\n * @param str text to make yellow\n */ export function yellow(str) {\n return run(str, code([\n 33\n ], 39));\n}\n/**\n * Set text color to blue.\n * @param str text to make blue\n */ export function blue(str) {\n return run(str, code([\n 34\n ], 39));\n}\n/**\n * Set text color to magenta.\n * @param str text to make magenta\n */ export function magenta(str) {\n return run(str, code([\n 35\n ], 39));\n}\n/**\n * Set text color to cyan.\n * @param str text to make cyan\n */ export function cyan(str) {\n return run(str, code([\n 36\n ], 39));\n}\n/**\n * Set text color to white.\n * @param str text to make white\n */ export function white(str) {\n return run(str, code([\n 37\n ], 39));\n}\n/**\n * Set text color to gray.\n * @param str text to make gray\n */ export function gray(str) {\n return brightBlack(str);\n}\n/**\n * Set text color to bright black.\n * @param str text to make bright-black\n */ export function brightBlack(str) {\n return run(str, code([\n 90\n ], 39));\n}\n/**\n * Set text color to bright red.\n * @param str text to make bright-red\n */ export function brightRed(str) {\n return run(str, code([\n 91\n ], 39));\n}\n/**\n * Set text color to bright green.\n * @param str text to make bright-green\n */ export function brightGreen(str) {\n return run(str, code([\n 92\n ], 39));\n}\n/**\n * Set text color to bright yellow.\n * @param str text to make bright-yellow\n */ export function brightYellow(str) {\n return run(str, code([\n 93\n ], 39));\n}\n/**\n * Set text color to bright blue.\n * @param str text to make bright-blue\n */ export function brightBlue(str) {\n return run(str, code([\n 94\n ], 39));\n}\n/**\n * Set text color to bright magenta.\n * @param str text to make bright-magenta\n */ export function brightMagenta(str) {\n return run(str, code([\n 95\n ], 39));\n}\n/**\n * Set text color to bright cyan.\n * @param str text to make bright-cyan\n */ export function brightCyan(str) {\n return run(str, code([\n 96\n ], 39));\n}\n/**\n * Set text color to bright white.\n * @param str text to make bright-white\n */ export function brightWhite(str) {\n return run(str, code([\n 97\n ], 39));\n}\n/**\n * Set background color to black.\n * @param str text to make its background black\n */ export function bgBlack(str) {\n return run(str, code([\n 40\n ], 49));\n}\n/**\n * Set background color to red.\n * @param str text to make its background red\n */ export function bgRed(str) {\n return run(str, code([\n 41\n ], 49));\n}\n/**\n * Set background color to green.\n * @param str text to make its background green\n */ export function bgGreen(str) {\n return run(str, code([\n 42\n ], 49));\n}\n/**\n * Set background color to yellow.\n * @param str text to make its background yellow\n */ export function bgYellow(str) {\n return run(str, code([\n 43\n ], 49));\n}\n/**\n * Set background color to blue.\n * @param str text to make its background blue\n */ export function bgBlue(str) {\n return run(str, code([\n 44\n ], 49));\n}\n/**\n * Set background color to magenta.\n * @param str text to make its background magenta\n */ export function bgMagenta(str) {\n return run(str, code([\n 45\n ], 49));\n}\n/**\n * Set background color to cyan.\n * @param str text to make its background cyan\n */ export function bgCyan(str) {\n return run(str, code([\n 46\n ], 49));\n}\n/**\n * Set background color to white.\n * @param str text to make its background white\n */ export function bgWhite(str) {\n return run(str, code([\n 47\n ], 49));\n}\n/**\n * Set background color to bright black.\n * @param str text to make its background bright-black\n */ export function bgBrightBlack(str) {\n return run(str, code([\n 100\n ], 49));\n}\n/**\n * Set background color to bright red.\n * @param str text to make its background bright-red\n */ export function bgBrightRed(str) {\n return run(str, code([\n 101\n ], 49));\n}\n/**\n * Set background color to bright green.\n * @param str text to make its background bright-green\n */ export function bgBrightGreen(str) {\n return run(str, code([\n 102\n ], 49));\n}\n/**\n * Set background color to bright yellow.\n * @param str text to make its background bright-yellow\n */ export function bgBrightYellow(str) {\n return run(str, code([\n 103\n ], 49));\n}\n/**\n * Set background color to bright blue.\n * @param str text to make its background bright-blue\n */ export function bgBrightBlue(str) {\n return run(str, code([\n 104\n ], 49));\n}\n/**\n * Set background color to bright magenta.\n * @param str text to make its background bright-magenta\n */ export function bgBrightMagenta(str) {\n return run(str, code([\n 105\n ], 49));\n}\n/**\n * Set background color to bright cyan.\n * @param str text to make its background bright-cyan\n */ export function bgBrightCyan(str) {\n return run(str, code([\n 106\n ], 49));\n}\n/**\n * Set background color to bright white.\n * @param str text to make its background bright-white\n */ export function bgBrightWhite(str) {\n return run(str, code([\n 107\n ], 49));\n}\n/* Special Color Sequences */ /**\n * Clam and truncate color codes\n * @param n\n * @param max number to truncate to\n * @param min number to truncate from\n */ function clampAndTruncate(n, max = 255, min = 0) {\n return Math.trunc(Math.max(Math.min(n, max), min));\n}\n/**\n * Set text color using paletted 8bit colors.\n * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit\n * @param str text color to apply paletted 8bit colors to\n * @param color code\n */ export function rgb8(str, color) {\n return run(str, code([\n 38,\n 5,\n clampAndTruncate(color)\n ], 39));\n}\n/**\n * Set background color using paletted 8bit colors.\n * https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit\n * @param str text color to apply paletted 8bit background colors to\n * @param color code\n */ export function bgRgb8(str, color) {\n return run(str, code([\n 48,\n 5,\n clampAndTruncate(color)\n ], 49));\n}\n/**\n * Set text color using 24bit rgb.\n * `color` can be a number in range `0x000000` to `0xffffff` or\n * an `Rgb`.\n *\n * To produce the color magenta:\n *\n * ```ts\n * import { rgb24 } from \"./colors.ts\";\n * rgb24(\"foo\", 0xff00ff);\n * rgb24(\"foo\", {r: 255, g: 0, b: 255});\n * ```\n * @param str text color to apply 24bit rgb to\n * @param color code\n */ export function rgb24(str, color) {\n if (typeof color === \"number\") {\n return run(str, code([\n 38,\n 2,\n color >> 16 & 255,\n color >> 8 & 255,\n color & 255\n ], 39));\n }\n return run(str, code([\n 38,\n 2,\n clampAndTruncate(color.r),\n clampAndTruncate(color.g),\n clampAndTruncate(color.b), \n ], 39));\n}\n/**\n * Set background color using 24bit rgb.\n * `color` can be a number in range `0x000000` to `0xffffff` or\n * an `Rgb`.\n *\n * To produce the color magenta:\n *\n * ```ts\n * import { bgRgb24 } from \"./colors.ts\";\n * bgRgb24(\"foo\", 0xff00ff);\n * bgRgb24(\"foo\", {r: 255, g: 0, b: 255});\n * ```\n * @param str text color to apply 24bit rgb to\n * @param color code\n */ export function bgRgb24(str, color) {\n if (typeof color === \"number\") {\n return run(str, code([\n 48,\n 2,\n color >> 16 & 255,\n color >> 8 & 255,\n color & 255\n ], 49));\n }\n return run(str, code([\n 48,\n 2,\n clampAndTruncate(color.r),\n clampAndTruncate(color.g),\n clampAndTruncate(color.b), \n ], 49));\n}\n// https://github.com/chalk/ansi-regex/blob/2b56fb0c7a07108e5b54241e8faec160d393aedb/index.js\nconst ANSI_PATTERN = new RegExp([\n \"[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:[a-zA-Z\\\\d]*(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)\",\n \"(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~]))\", \n].join(\"|\"), \"g\");\n/**\n * Remove ANSI escape codes from the string.\n * @param string to remove ANSI escape codes from\n */ export function stripColor(string) {\n return string.replace(ANSI_PATTERN, \"\");\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9mbXQvY29sb3JzLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQUEwRSxBQUExRSx3RUFBMEU7QUFDMUUsRUFBK0UsQUFBL0UsNkVBQStFO0FBQy9FLEVBQVUsQUFBVixRQUFVO0FBQ1YsRUFBRTtBQUVGLEVBVUcsQUFWSDs7Ozs7Ozs7OztDQVVHLEFBVkgsRUFVRyxDQUNILEVBQXFDLEFBQXJDLG1DQUFxQztBQUVyQyxFQUFtQyxBQUFuQyxpQ0FBbUM7QUFDbkMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUMsQ0FBQyxHQUFHLFVBQVU7QUFDM0IsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxFQUFFLE9BQU8sS0FBSyxDQUFTLFdBQzlDLElBQUksQ0FBQyxPQUFPLEdBQ1osSUFBSTtBQWVSLEdBQUcsQ0FBQyxPQUFPLElBQUksT0FBTztBQUV0QixFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBYyxFQUFRLENBQUM7SUFDckQsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ1osTUFBTTtJQUNSLENBQUM7SUFFRCxPQUFPLEdBQUcsS0FBSztBQUNqQixDQUFDO0FBRUQsRUFBNEQsQUFBNUQsd0RBQTRELEFBQTVELEVBQTRELENBQzVELE1BQU0sVUFBVSxlQUFlLEdBQVksQ0FBQztJQUMxQyxNQUFNLENBQUMsT0FBTztBQUNoQixDQUFDO0FBRUQsRUFJRyxBQUpIOzs7O0NBSUcsQUFKSCxFQUlHLFVBQ00sSUFBSSxDQUFDLElBQWMsRUFBRSxLQUFhLEVBQVEsQ0FBQztJQUNsRCxNQUFNLENBQUMsQ0FBQztRQUNOLElBQUksR0FBRyxLQUFLLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFHLElBQUUsQ0FBQztRQUM5QixLQUFLLEdBQUcsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3RCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUc7SUFDN0MsQ0FBQztBQUNILENBQUM7QUFFRCxFQUlHLEFBSkg7Ozs7Q0FJRyxBQUpILEVBSUcsVUFDTSxHQUFHLENBQUMsR0FBVyxFQUFFLElBQVUsRUFBVSxDQUFDO0lBQzdDLE1BQU0sQ0FBQyxPQUFPLE1BQ1AsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxLQUMvRCxHQUFHO0FBQ1QsQ0FBQztBQUVELEVBR0csQUFISDs7O0NBR0csQUFISCxFQUdHLENBQ0gsTUFBTSxVQUFVLEtBQUssQ0FBQyxHQUFXLEVBQVUsQ0FBQztJQUMxQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUFBLENBQUM7SUFBQSxDQUFDLEVBQUUsQ0FBQztBQUM3QixDQUFDO0FBRUQsRUFHRyxBQUhIOzs7Q0FHRyxBQUhILEVBR0csQ0FDSCxNQUFNLFVBQVUsSUFBSSxDQUFDLEdBQVcsRUFBVSxDQUFDO0lBQ3pDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQUEsQ0FBQztJQUFBLENBQUMsRUFBRSxFQUFFO0FBQzlCLENBQUM7QUFFRCxFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxHQUFHLENBQUMsR0FBVyxFQUFVLENBQUM7SUFDeEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFBQSxDQUFDO0lBQUEsQ0FBQyxFQUFFLEVBQUU7QUFDOUIsQ0FBQztBQUVELEVBR0csQUFISDs7O0NBR0csQUFISCxFQUdHLENBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxHQUFXLEVBQVUsQ0FBQztJQUMzQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUFBLENBQUM7SUFBQSxDQUFDLEVBQUUsRUFBRTtBQUM5QixDQUFDO0FBRUQsRUFHRyxBQUhIOzs7Q0FHRyxBQUhILEVBR0csQ0FDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQVcsRUFBVSxDQUFDO0lBQzlDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQUEsQ0FBQztJQUFBLENBQUMsRUFBRSxFQUFFO0FBQzlCLENBQUM7QUFFRCxFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxPQUFPLENBQUMsR0FBVyxFQUFVLENBQUM7SUFDNUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFBQSxDQUFDO0lBQUEsQ0FBQyxFQUFFLEVBQUU7QUFDOUIsQ0FBQztBQUVELEVBR0csQUFISDs7O0NBR0csQUFISCxFQUdHLENBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxHQUFXLEVBQVUsQ0FBQztJQUMzQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUFBLENBQUM7SUFBQSxDQUFDLEVBQUUsRUFBRTtBQUM5QixDQUFDO0FBRUQsRUFHRyxBQUhIOzs7Q0FHRyxBQUhILEVBR0csQ0FDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLEdBQVcsRUFBVSxDQUFDO0lBQ2xELE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQUEsQ0FBQztJQUFBLENBQUMsRUFBRSxFQUFFO0FBQzlCLENBQUM7QUFFRCxFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxLQUFLLENBQUMsR0FBVyxFQUFVLENBQUM7SUFDMUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFBQSxFQUFFO0lBQUEsQ0FBQyxFQUFFLEVBQUU7QUFDL0IsQ0FBQztBQUVELEVBR0csQUFISDs7O0NBR0csQUFISCxFQUdHLENBQ0gsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFXLEVBQVUsQ0FBQztJQUN4QyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUFBLEVBQUU7SUFBQSxDQUFDLEVBQUUsRUFBRTtBQUMvQixDQUFDO0FBRUQsRUFHRyxBQUhIOzs7Q0FHRyxBQUhILEVBR0csQ0FDSCxNQUFNLFVBQVUsS0FBSyxDQUFDLEdBQVcsRUFBVSxDQUFDO0lBQzFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQUEsRUFBRTtJQUFBLENBQUMsRUFBRSxFQUFFO0FBQy9CLENBQUM7QUFFRCxFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxNQUFNLENBQUMsR0FBVyxFQUFVLENBQUM7SUFDM0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFBQSxFQUFFO0lBQUEsQ0FBQyxFQUFFLEVBQUU7QUFDL0IsQ0FBQztBQUVELEVBR0csQUFISDs7O0NBR0csQUFISCxFQUdHLENBQ0gsTUFBTSxVQUFVLElBQUksQ0FBQyxHQUFXLEVBQVUsQ0FBQztJQUN6QyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUFBLEVBQUU7SUFBQSxDQUFDLEVBQUUsRUFBRTtBQUMvQixDQUFDO0FBRUQsRUFHRyxBQUhIOzs7Q0FHRyxBQUhILEVBR0csQ0FDSCxNQUFNLFVBQVUsT0FBTyxDQUFDLEdBQVcsRUFBVSxDQUFDO0lBQzVDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQUEsRUFBRTtJQUFBLENBQUMsRUFBRSxFQUFFO0FBQy9CLENBQUM7QUFFRCxFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxJQUFJLENBQUMsR0FBVyxFQUFVLENBQUM7SUFDekMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFB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QixDQUFDO0FBRUQsRUFHRyxBQUhIOzs7Q0FHRyxBQUhILEVBR0csQ0FDSCxNQUFNLFVBQVUsS0FBSyxDQUFDLEdBQVcsRUFBVSxDQUFDO0lBQzFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQUEsRUFBRTtJQUFBLENBQUMsRUFBRSxFQUFFO0FBQy9CLENBQUM7QUFFRCxFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxPQUFPLENBQUMsR0FBVyxFQUFVLENBQUM7SUFDNUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFBQSxFQUFFO0lBQUEsQ0FBQyxFQUFFLEVBQUU7QUFDL0IsQ0FBQztBQUVELEVBR0csQUFISDs7O0NBR0csQUFISCxFQUdHLENBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxHQUFXLEVBQVUsQ0FBQztJQUM3QyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUFBLEVBQUU7SUFBQSxDQUFDLEVBQUUsRUFBRTtBQUMvQixDQUFDO0FBRUQsRUFHRyxBQUhIOzs7Q0FHRyxBQUhILEVBR0csQ0FDSCxNQUFNLFVBQVUsTUFBTSxDQUFDLEdBQVcsRUFBVSxDQUFDO0lBQzNDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQUEsRUFBRTtJQUFBLENBQUMsRUFBRSxFQUFFO0FBQy9CLENBQUM7QUFFRCxFQUdHLEFBSEg7OztDQUdHLEFBSEgsRUFHRyxDQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsR0FBVyxFQUFVLENBQUM7SUFDOUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFBQSxFQUFFO0lBQUEsQ0FBQyxFQUFFLEVBQUU7QUFDL0IsQ0FBQztBQUVELEVBR0csQUFISDs7O0NBR0csQUFISCxFQUdHLENBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxHQUFXLEVBQVUsQ0FBQztJ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", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.120.0/async/delay.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\nexport interface DelayOptions {\n signal?: AbortSignal;\n}\n\n/* Resolves after the given number of milliseconds. */\nexport function delay(ms: number, options: DelayOptions = {}): Promise {\n const { signal } = options;\n if (signal?.aborted) {\n return Promise.reject(new DOMException(\"Delay was aborted.\", \"AbortError\"));\n }\n return new Promise((resolve, reject): void => {\n const abort = () => {\n clearTimeout(i);\n reject(new DOMException(\"Delay was aborted.\", \"AbortError\"));\n };\n const done = () => {\n signal?.removeEventListener(\"abort\", abort);\n resolve();\n };\n const i = setTimeout(done, ms);\n signal?.addEventListener(\"abort\", abort, { once: true });\n });\n}\n", - "transpiled": "/* Resolves after the given number of milliseconds. */ export function delay(ms, options = {\n}) {\n const { signal } = options;\n if (signal?.aborted) {\n return Promise.reject(new DOMException(\"Delay was aborted.\", \"AbortError\"));\n }\n return new Promise((resolve, reject)=>{\n const abort = ()=>{\n clearTimeout(i);\n reject(new DOMException(\"Delay was aborted.\", \"AbortError\"));\n };\n const done = ()=>{\n signal?.removeEventListener(\"abort\", abort);\n resolve();\n };\n const i = setTimeout(done, ms);\n signal?.addEventListener(\"abort\", abort, {\n once: true\n });\n });\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy9kZWxheS50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUEsRUFBc0QsQUFBdEQsa0RBQXNELEFBQXRELEVBQXNELENBQ3RELE1BQU0sVUFBVSxLQUFLLENBQUMsRUFBVSxFQUFFLE9BQXFCLEdBQUcsQ0FBQztBQUFBLENBQUMsRUFBaUIsQ0FBQztJQUM1RSxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBQyxDQUFDLEdBQUcsT0FBTztJQUMxQixFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBb0IscUJBQUUsQ0FBWTtJQUMzRSxDQUFDO0lBQ0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sR0FBVyxDQUFDO1FBQzdDLEtBQUssQ0FBQyxLQUFLLE9BQVMsQ0FBQztZQUNuQixZQUFZLENBQUMsQ0FBQztZQUNkLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQW9CLHFCQUFFLENBQVk7UUFDNUQsQ0FBQztRQUNELEtBQUssQ0FBQyxJQUFJLE9BQVMsQ0FBQztZQUNsQixNQUFNLEVBQUUsbUJBQW1CLENBQUMsQ0FBTyxRQUFFLEtBQUs7WUFDMUMsT0FBTztRQUNULENBQUM7UUFDRCxLQUFLLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUM3QixNQUFNLEVBQUUsZ0JBQWdCLENBQUMsQ0FBTyxRQUFFLEtBQUssRUFBRSxDQUFDO1lBQUMsSUFBSSxFQUFFLElBQUk7UUFBQyxDQUFDO0lBQ3pELENBQUM7QUFDSCxDQUFDIn0=", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/x/oak_commons@0.1.1/negotiation/encoding.ts": { - "Source": { - "source": "/*!\n * Adapted directly from negotiator at https://github.com/jshttp/negotiator/\n * which is licensed as follows:\n *\n * (The MIT License)\n *\n * Copyright (c) 2012-2014 Federico Romero\n * Copyright (c) 2012-2014 Isaac Z. Schlueter\n * Copyright (c) 2014-2015 Douglas Christopher Wilson\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nimport { compareSpecs, isQuality, Specificity } from \"./common.ts\";\n\ninterface EncodingSpecificty extends Specificity {\n encoding?: string;\n}\n\nconst simpleEncodingRegExp = /^\\s*([^\\s;]+)\\s*(?:;(.*))?$/;\n\nfunction parseEncoding(str: string, i: number): EncodingSpecificty | undefined {\n const match = simpleEncodingRegExp.exec(str);\n if (!match) {\n return undefined;\n }\n\n const encoding = match[1];\n let q = 1;\n if (match[2]) {\n const params = match[2].split(\";\");\n for (const param of params) {\n const p = param.trim().split(\"=\");\n if (p[0] === \"q\") {\n q = parseFloat(p[1]);\n break;\n }\n }\n }\n\n return { encoding, q, i };\n}\n\nfunction specify(\n encoding: string,\n spec: EncodingSpecificty,\n i = -1,\n): Specificity | undefined {\n if (!spec.encoding) {\n return;\n }\n let s = 0;\n if (spec.encoding.toLocaleLowerCase() === encoding.toLocaleLowerCase()) {\n s = 1;\n } else if (spec.encoding !== \"*\") {\n return;\n }\n\n return {\n i,\n o: spec.i,\n q: spec.q,\n s,\n };\n}\n\nfunction parseAcceptEncoding(accept: string): EncodingSpecificty[] {\n const accepts = accept.split(\",\");\n const parsedAccepts: EncodingSpecificty[] = [];\n let hasIdentity = false;\n let minQuality = 1;\n\n for (let i = 0; i < accepts.length; i++) {\n const encoding = parseEncoding(accepts[i].trim(), i);\n\n if (encoding) {\n parsedAccepts.push(encoding);\n hasIdentity = hasIdentity || !!specify(\"identity\", encoding);\n minQuality = Math.min(minQuality, encoding.q || 1);\n }\n }\n\n if (!hasIdentity) {\n parsedAccepts.push({\n encoding: \"identity\",\n q: minQuality,\n i: accepts.length - 1,\n });\n }\n\n return parsedAccepts;\n}\n\nfunction getEncodingPriority(\n encoding: string,\n accepted: Specificity[],\n index: number,\n): Specificity {\n let priority: Specificity = { o: -1, q: 0, s: 0, i: 0 };\n\n for (const s of accepted) {\n const spec = specify(encoding, s, index);\n\n if (\n spec &&\n (priority.s! - spec.s! || priority.q - spec.q ||\n priority.o! - spec.o!) <\n 0\n ) {\n priority = spec;\n }\n }\n\n return priority;\n}\n\n/** Given an `Accept-Encoding` string, parse out the encoding returning a\n * negotiated encoding based on the `provided` encodings otherwise just a\n * prioritized array of encodings. */\nexport function preferredEncodings(\n accept: string,\n provided?: string[],\n): string[] {\n const accepts = parseAcceptEncoding(accept);\n\n if (!provided) {\n return accepts\n .filter(isQuality)\n .sort(compareSpecs)\n .map((spec) => spec.encoding!);\n }\n\n const priorities = provided.map((type, index) =>\n getEncodingPriority(type, accepts, index)\n );\n\n return priorities\n .filter(isQuality)\n .sort(compareSpecs)\n .map((priority) => provided[priorities.indexOf(priority)]);\n}\n", - "transpiled": "/*!\n * Adapted directly from negotiator at https://github.com/jshttp/negotiator/\n * which is licensed as follows:\n *\n * (The MIT License)\n *\n * Copyright (c) 2012-2014 Federico Romero\n * Copyright (c) 2012-2014 Isaac Z. Schlueter\n * Copyright (c) 2014-2015 Douglas Christopher Wilson\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */ import { compareSpecs, isQuality } from \"./common.ts\";\nconst simpleEncodingRegExp = /^\\s*([^\\s;]+)\\s*(?:;(.*))?$/;\nfunction parseEncoding(str, i) {\n const match = simpleEncodingRegExp.exec(str);\n if (!match) {\n return undefined;\n }\n const encoding = match[1];\n let q = 1;\n if (match[2]) {\n const params = match[2].split(\";\");\n for (const param of params){\n const p = param.trim().split(\"=\");\n if (p[0] === \"q\") {\n q = parseFloat(p[1]);\n break;\n }\n }\n }\n return {\n encoding,\n q,\n i\n };\n}\nfunction specify(encoding, spec, i = -1) {\n if (!spec.encoding) {\n return;\n }\n let s = 0;\n if (spec.encoding.toLocaleLowerCase() === encoding.toLocaleLowerCase()) {\n s = 1;\n } else if (spec.encoding !== \"*\") {\n return;\n }\n return {\n i,\n o: spec.i,\n q: spec.q,\n s\n };\n}\nfunction parseAcceptEncoding(accept) {\n const accepts = accept.split(\",\");\n const parsedAccepts = [];\n let hasIdentity = false;\n let minQuality = 1;\n for(let i = 0; i < accepts.length; i++){\n const encoding = parseEncoding(accepts[i].trim(), i);\n if (encoding) {\n parsedAccepts.push(encoding);\n hasIdentity = hasIdentity || !!specify(\"identity\", encoding);\n minQuality = Math.min(minQuality, encoding.q || 1);\n }\n }\n if (!hasIdentity) {\n parsedAccepts.push({\n encoding: \"identity\",\n q: minQuality,\n i: accepts.length - 1\n });\n }\n return parsedAccepts;\n}\nfunction getEncodingPriority(encoding, accepted, index) {\n let priority = {\n o: -1,\n q: 0,\n s: 0,\n i: 0\n };\n for (const s of accepted){\n const spec = specify(encoding, s, index);\n if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {\n priority = spec;\n }\n }\n return priority;\n}\n/** Given an `Accept-Encoding` string, parse out the encoding returning a\n * negotiated encoding based on the `provided` encodings otherwise just a\n * prioritized array of encodings. */ export function preferredEncodings(accept, provided) {\n const accepts = parseAcceptEncoding(accept);\n if (!provided) {\n return accepts.filter(isQuality).sort(compareSpecs).map((spec)=>spec.encoding\n );\n }\n const priorities = provided.map((type, index)=>getEncodingPriority(type, accepts, index)\n );\n return priorities.filter(isQuality).sort(compareSpecs).map((priority)=>provided[priorities.indexOf(priority)]\n );\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L29ha19jb21tb25zQDAuMS4xL25lZ290aWF0aW9uL2VuY29kaW5nLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQTRCRyxBQTVCSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQTRCRyxBQTVCSCxFQTRCRyxDQUVILE1BQU0sR0FBRyxZQUFZLEVBQUUsU0FBUyxRQUFxQixDQUFhO0FBTWxFLEtBQUssQ0FBQyxvQkFBb0I7U0FFakIsYUFBYSxDQUFDLEdBQVcsRUFBRSxDQUFTLEVBQWtDLENBQUM7SUFDOUUsS0FBSyxDQUFDLEtBQUssR0FBRyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsR0FBRztJQUMzQyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUM7UUFDWCxNQUFNLENBQUMsU0FBUztJQUNsQixDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsQ0FBQztJQUN4QixHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDVCxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ2IsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFHO1FBQ2pDLEdBQUcsRUFBRSxLQUFLLENBQUMsS0FBSyxJQUFJLE1BQU0sQ0FBRSxDQUFDO1lBQzNCLEtBQUssQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBRztZQUNoQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFHLElBQUUsQ0FBQztnQkFDakIsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDbEIsS0FBSztZQUNQLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sQ0FBQyxDQUFDO1FBQUMsUUFBUTtRQUFFLENBQUM7UUFBRSxDQUFDO0lBQUMsQ0FBQztBQUMzQixDQUFDO1NBRVEsT0FBTyxDQUNk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", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/x/oak_commons@0.1.1/negotiation/common.ts"] - } - }, - "https://deno.land/std@0.108.0/async/pool.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n/**\n * pooledMap transforms values from an (async) iterable into another async\n * iterable. The transforms are done concurrently, with a max concurrency\n * defined by the poolLimit.\n *\n * If an error is thrown from `iterableFn`, no new transformations will begin.\n * All currently executing transformations are allowed to finish and still\n * yielded on success. After that, the rejections among them are gathered and\n * thrown by the iterator in an `AggregateError`.\n *\n * @param poolLimit The maximum count of items being processed concurrently.\n * @param array The input array for mapping.\n * @param iteratorFn The function to call for every item of the array.\n */\nexport function pooledMap(\n poolLimit: number,\n array: Iterable | AsyncIterable,\n iteratorFn: (data: T) => Promise,\n): AsyncIterableIterator {\n // Create the async iterable that is returned from this function.\n const res = new TransformStream, R>({\n async transform(\n p: Promise,\n controller: TransformStreamDefaultController,\n ) {\n controller.enqueue(await p);\n },\n });\n // Start processing items from the iterator\n (async () => {\n const writer = res.writable.getWriter();\n const executing: Array> = [];\n try {\n for await (const item of array) {\n const p = Promise.resolve().then(() => iteratorFn(item));\n // Only write on success. If we `writer.write()` a rejected promise,\n // that will end the iteration. We don't want that yet. Instead let it\n // fail the race, taking us to the catch block where all currently\n // executing jobs are allowed to finish and all rejections among them\n // can be reported together.\n p.then((v) => writer.write(Promise.resolve(v))).catch(() => {});\n const e: Promise = p.then(() =>\n executing.splice(executing.indexOf(e), 1)\n );\n executing.push(e);\n if (executing.length >= poolLimit) {\n await Promise.race(executing);\n }\n }\n // Wait until all ongoing events have processed, then close the writer.\n await Promise.all(executing);\n writer.close();\n } catch {\n const errors = [];\n for (const result of await Promise.allSettled(executing)) {\n if (result.status == \"rejected\") {\n errors.push(result.reason);\n }\n }\n writer.write(Promise.reject(\n new AggregateError(errors, \"Threw while mapping.\"),\n )).catch(() => {});\n }\n })();\n return res.readable[Symbol.asyncIterator]();\n}\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n/**\n * pooledMap transforms values from an (async) iterable into another async\n * iterable. The transforms are done concurrently, with a max concurrency\n * defined by the poolLimit.\n *\n * If an error is thrown from `iterableFn`, no new transformations will begin.\n * All currently executing transformations are allowed to finish and still\n * yielded on success. After that, the rejections among them are gathered and\n * thrown by the iterator in an `AggregateError`.\n *\n * @param poolLimit The maximum count of items being processed concurrently.\n * @param array The input array for mapping.\n * @param iteratorFn The function to call for every item of the array.\n */ export function pooledMap(poolLimit, array, iteratorFn) {\n // Create the async iterable that is returned from this function.\n const res = new TransformStream({\n async transform (p, controller) {\n controller.enqueue(await p);\n }\n });\n // Start processing items from the iterator\n (async ()=>{\n const writer = res.writable.getWriter();\n const executing = [];\n try {\n for await (const item of array){\n const p = Promise.resolve().then(()=>iteratorFn(item)\n );\n // Only write on success. If we `writer.write()` a rejected promise,\n // that will end the iteration. We don't want that yet. Instead let it\n // fail the race, taking us to the catch block where all currently\n // executing jobs are allowed to finish and all rejections among them\n // can be reported together.\n p.then((v)=>writer.write(Promise.resolve(v))\n ).catch(()=>{\n });\n const e = p.then(()=>executing.splice(executing.indexOf(e), 1)\n );\n executing.push(e);\n if (executing.length >= poolLimit) {\n await Promise.race(executing);\n }\n }\n // Wait until all ongoing events have processed, then close the writer.\n await Promise.all(executing);\n writer.close();\n } catch {\n const errors = [];\n for (const result of (await Promise.allSettled(executing))){\n if (result.status == \"rejected\") {\n errors.push(result.reason);\n }\n }\n writer.write(Promise.reject(new AggregateError(errors, \"Threw while mapping.\"))).catch(()=>{\n });\n }\n })();\n return res.readable[Symbol.asyncIterator]();\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy9wb29sLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQUEwRSxBQUExRSx3RUFBMEU7QUFFMUUsRUFhRyxBQWJIOzs7Ozs7Ozs7Ozs7O0NBYUcsQUFiSCxFQWFHLENBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FDdkIsU0FBaUIsRUFDakIsS0FBcUMsRUFDckMsVUFBbUMsRUFDVCxDQUFDO0lBQzNCLEVBQWlFLEFBQWpFLCtEQUFpRTtJQUNqRSxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQWdCLENBQUM7Y0FDeEMsU0FBUyxFQUNiLENBQWEsRUFDYixVQUErQyxFQUMvQyxDQUFDO1lBQ0QsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQztJQUNELEVBQTJDLEFBQTNDLHlDQUEyQztlQUM5QixDQUFDO1FBQ1osS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFNBQVM7UUFDckMsS0FBSyxDQUFDLFNBQVMsR0FBNEIsQ0FBQyxDQUFDO1FBQzdDLEdBQUcsQ0FBQyxDQUFDO1lBQ0gsR0FBRyxRQUFRLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFFLENBQUM7Z0JBQy9CLEtBQUssQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sR0FBRyxJQUFJLEtBQU8sVUFBVSxDQUFDLElBQUk7O2dCQUN0RCxFQUFvRSxBQUFwRSxrRUFBb0U7Z0JBQ3BFLEVBQXNFLEFBQXRFLG9FQUFzRTtnQkFDdEUsRUFBa0UsQUFBbEUsZ0VBQWtFO2dCQUNsRSxFQUFxRSxBQUFyRSxtRUFBcUU7Z0JBQ3JFLEVBQTRCLEFBQTVCLDBCQUE0QjtnQkFDNUIsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7a0JBQUksS0FBSyxLQUFPLENBQUM7Z0JBQUEsQ0FBQztnQkFDOUQsS0FBSyxDQUFDLENBQUMsR0FBcUIsQ0FBQyxDQUFDLElBQUksS0FDaEMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDOztnQkFFMUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNoQixFQUFFLEVBQUUsU0FBUyxDQUFDLE1BQU0sSUFBSSxTQUFTLEVBQUUsQ0FBQztvQkFDbEMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUztnQkFDOUIsQ0FBQztZQUNILENBQUM7WUFDRCxFQUF1RSxBQUF2RSxxRUFBdUU7WUFDdkUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUztZQUMzQixNQUFNLENBQUMsS0FBSztRQUNkLENBQUMsQ0FBQyxLQUFLLEVBQUMsQ0FBQztZQUNQLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLEdBQUcsRUFBRSxLQUFLLENBQUMsTUFBTSxLQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsR0FBRyxDQUFDO2dCQUN6RCxFQUFFLEVBQUUsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFVLFdBQUUsQ0FBQztvQkFDaEMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTtnQkFDM0IsQ0FBQztZQUNILENBQUM7WUFDRCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQ3pCLEdBQUcsQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQXNCLHlCQUNoRCxLQUFLLEtBQU8sQ0FBQztZQUFBLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsYUFBYTtBQUMxQyxDQUFDIn0=", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.108.0/async/debounce.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n/**\n * A debounced function that will be delayed by a given `wait`\n * time in milliseconds. If the method is called again before\n * the timeout expires, the previous call will be aborted.\n */\nexport interface DebouncedFunction> {\n (...args: T): void;\n /** Clears the debounce timeout and omits calling the debounced function. */\n clear(): void;\n /** Clears the debounce timeout and calls the debounced function immediately. */\n flush(): void;\n /** Returns a boolean wether a debounce call is pending or not. */\n readonly pending: boolean;\n}\n\n/**\n * Creates a debounced function that delays the given `func`\n * by a given `wait` time in milliseconds. If the method is called\n * again before the timeout expires, the previous call will be\n * aborted.\n *\n * ```\n * import { debounce } from \"./debounce.ts\";\n *\n * const log = debounce(\n * (event: Deno.FsEvent) =>\n * console.log(\"[%s] %s\", event.kind, event.paths[0]),\n * 200,\n * );\n *\n * for await (const event of Deno.watchFs(\"./\")) {\n * log(event);\n * }\n * ```\n *\n * @param fn The function to debounce.\n * @param wait The time in milliseconds to delay the function.\n */\n// deno-lint-ignore no-explicit-any\nexport function debounce>(\n fn: (this: DebouncedFunction, ...args: T) => void,\n wait: number,\n): DebouncedFunction {\n let timeout: number | null = null;\n let flush: (() => void) | null = null;\n\n const debounced: DebouncedFunction = ((...args: T): void => {\n debounced.clear();\n flush = (): void => {\n debounced.clear();\n fn.call(debounced, ...args);\n };\n timeout = setTimeout(flush, wait);\n }) as DebouncedFunction;\n\n debounced.clear = (): void => {\n if (typeof timeout === \"number\") {\n clearTimeout(timeout);\n timeout = null;\n flush = null;\n }\n };\n\n debounced.flush = (): void => {\n flush?.();\n };\n\n Object.defineProperty(debounced, \"pending\", {\n get: () => typeof timeout === \"number\",\n });\n\n return debounced;\n}\n", - "transpiled": "/**\n * Creates a debounced function that delays the given `func`\n * by a given `wait` time in milliseconds. If the method is called\n * again before the timeout expires, the previous call will be\n * aborted.\n *\n * ```\n * import { debounce } from \"./debounce.ts\";\n *\n * const log = debounce(\n * (event: Deno.FsEvent) =>\n * console.log(\"[%s] %s\", event.kind, event.paths[0]),\n * 200,\n * );\n *\n * for await (const event of Deno.watchFs(\"./\")) {\n * log(event);\n * }\n * ```\n *\n * @param fn The function to debounce.\n * @param wait The time in milliseconds to delay the function.\n */ // deno-lint-ignore no-explicit-any\nexport function debounce(fn, wait) {\n let timeout = null;\n let flush = null;\n const debounced = (...args)=>{\n debounced.clear();\n flush = ()=>{\n debounced.clear();\n fn.call(debounced, ...args);\n };\n timeout = setTimeout(flush, wait);\n };\n debounced.clear = ()=>{\n if (typeof timeout === \"number\") {\n clearTimeout(timeout);\n timeout = null;\n flush = null;\n }\n };\n debounced.flush = ()=>{\n flush?.();\n };\n Object.defineProperty(debounced, \"pending\", {\n get: ()=>typeof timeout === \"number\"\n });\n return debounced;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy9kZWJvdW5jZS50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUJBLEVBc0JHLEFBdEJIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBc0JHLEFBdEJILEVBc0JHLENBQ0gsRUFBbUMsQUFBbkMsaUNBQW1DO0FBQ25DLE1BQU0sVUFBVSxRQUFRLENBQ3RCLEVBQW9ELEVBQ3BELElBQVksRUFDVSxDQUFDO0lBQ3ZCLEdBQUcsQ0FBQyxPQUFPLEdBQWtCLElBQUk7SUFDakMsR0FBRyxDQUFDLEtBQUssR0FBd0IsSUFBSTtJQUVyQyxLQUFLLENBQUMsU0FBUyxPQUE4QixJQUFJLEdBQWMsQ0FBQztRQUM5RCxTQUFTLENBQUMsS0FBSztRQUNmLEtBQUssT0FBZSxDQUFDO1lBQ25CLFNBQVMsQ0FBQyxLQUFLO1lBQ2YsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEtBQUssSUFBSTtRQUM1QixDQUFDO1FBQ0QsT0FBTyxHQUFHLFVBQVUsQ0FBQyxLQUFLLEVBQUUsSUFBSTtJQUNsQyxDQUFDO0lBRUQsU0FBUyxDQUFDLEtBQUssT0FBZSxDQUFDO1FBQzdCLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTyxLQUFLLENBQVEsU0FBRSxDQUFDO1lBQ2hDLFlBQVksQ0FBQyxPQUFPO1lBQ3BCLE9BQU8sR0FBRyxJQUFJO1lBQ2QsS0FBSyxHQUFHLElBQUk7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVELFNBQVMsQ0FBQyxLQUFLLE9BQWUsQ0FBQztRQUM3QixLQUFLO0lBQ1AsQ0FBQztJQUVELE1BQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxFQUFFLENBQVMsVUFBRSxDQUFDO1FBQzNDLEdBQUcsTUFBUSxNQUFNLENBQUMsT0FBTyxLQUFLLENBQVE7SUFDeEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxTQUFTO0FBQ2xCLENBQUMifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "file:///src/worker/registry.ts": { - "Source": { - "source": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */\n\nimport { parseNameVersion } from \"../util/registry_utils.ts\";\n\nexport const S3_BUCKET =\n \"http://deno-registry2-prod-storagebucket-b3a31d16.s3-website-us-east-1.amazonaws.com/\";\n\n/** Handle _legacy_ v1 registry requests. v2 is handled by `./suggestions.ts`.\n */\nexport async function handleRegistryRequest(url: URL): Promise {\n const entry = parsePathname(url.pathname);\n if (!entry) {\n return new Response(\"This module entry is invalid: \" + url.pathname, {\n status: 400,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n const { module, version, path } = entry;\n if (!version) {\n const latest = await getLatestVersion(module);\n if (!latest) {\n return new Response(\n \"This module has no latest version: \" + url.pathname,\n {\n status: 404,\n headers: { \"content-type\": \"text/plain\" },\n },\n );\n }\n return new Response(undefined, {\n headers: {\n Location: `${module === \"std\" ? \"\" : \"/x\"}/${module}@${latest}/${path}`,\n \"x-deno-warning\":\n `Implicitly using latest version (${latest}) for ${url.origin}${\n module === \"std\" ? \"\" : \"/x\"\n }/${module}/${path}`,\n },\n status: 302,\n });\n }\n if (version.startsWith(\"v0.\") && module === \"std\") {\n const correctVersion = version.substring(1);\n const versionNumber = parseFloat(correctVersion);\n // For now only block std versions >= 0.43.0\n // Timeline for deprecation:\n // Oct 14 2020: >= 0.70.0\n // Oct 21 2020: >= 0.68.0\n // Oct 28 2020: >= 0.65.0\n // Nov 04 2020: >= 0.61.0\n // Nov 11 2020: >= 0.56.0\n // Nov 18 2020: >= 0.50.0\n // Nov 25 2020: >= 0.43.0\n // Dec 02 2020: >= 0.34.0 (oldest available std release)\n if (versionNumber >= 0.43) {\n return new Response(\"404 Not Found\", {\n headers: {\n \"x-deno-warning\":\n `std versions prefixed with 'v' were deprecated recently. Please change your import to ${url.origin}${\n module === \"std\" ? \"\" : \"/x\"\n }/${module}@${correctVersion}/${path} (at ${url.origin}${\n module === \"std\" ? \"\" : \"/x\"\n }/${module}@${version}/${path})`,\n },\n status: 404,\n });\n }\n return new Response(undefined, {\n headers: {\n Location: `/std@${correctVersion}/${path}`,\n \"x-deno-warning\":\n `std versions prefixed with 'v' will be deprecated soon. Please change your import to ${url.origin}${\n module === \"std\" ? \"\" : \"/x\"\n }/${module}@${correctVersion}/${path} (at ${url.origin}${\n module === \"std\" ? \"\" : \"/x\"\n }/${module}@${version}/${path})`,\n },\n status: 302,\n });\n }\n const remoteUrl = getBackingURL(module, version, path);\n const resp2 = await fetchSource(remoteUrl);\n\n // JSX and TSX content type fix\n if (\n remoteUrl.endsWith(\".jsx\") &&\n !resp2.headers.get(\"content-type\")?.includes(\"javascript\")\n ) {\n resp2.headers.set(\"content-type\", \"application/javascript\");\n } else if (\n remoteUrl.endsWith(\".tsx\") &&\n !resp2.headers.get(\"content-type\")?.includes(\"typescript\")\n ) {\n resp2.headers.set(\"content-type\", \"application/typescript\");\n }\n\n resp2.headers.set(\"Access-Control-Allow-Origin\", \"*\");\n return resp2;\n}\n\nexport function parsePathname(\n pathname: string,\n): { module: string; version: string | undefined; path: string } | undefined {\n if (pathname.startsWith(\"/std\")) {\n return parsePathname(\"/x\" + pathname);\n }\n if (!pathname.startsWith(\"/x/\")) {\n return undefined;\n }\n pathname = decodeURIComponent(pathname);\n const nameBranchRest = pathname.replace(/^\\/x\\//, \"\");\n const [nameBranch, ...rest] = nameBranchRest.split(\"/\");\n const [name, version] = parseNameVersion(nameBranch);\n const path = rest.join(\"/\");\n return { module: name, version, path };\n}\n\nexport function getBackingURL(module: string, version: string, path: string) {\n return `${S3_BUCKET}${module}/versions/${version}/raw/${path}`;\n}\n\nexport async function fetchSource(remoteUrl: string) {\n let lastErr;\n for (let i = 0; i < 3; i++) {\n try {\n const resp = await fetch(remoteUrl);\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"404 Not Found\", { status: 404 });\n }\n if (!resp.ok) throw new TypeError(\"non 2xx status code returned\");\n return new Response(resp.body, {\n headers: resp.headers,\n status: resp.status,\n });\n } catch (err) {\n // TODO(lucacasonato): only retry on known retryable errors\n console.warn(\"retrying on proxy error\", err);\n lastErr = err;\n }\n }\n throw lastErr;\n}\n\nexport async function getLatestVersion(\n module: string,\n): Promise {\n let lastErr;\n for (let i = 0; i < 3; i++) {\n try {\n const res = await fetch(`${S3_BUCKET}${module}/meta/versions.json`);\n if (res.status === 404 || res.status === 403) return undefined;\n if (!res.ok) throw new TypeError(\"non 2xx status code returned\");\n const versions = await res.json();\n return versions?.latest;\n } catch (err) {\n // TODO(lucacasonato): only retry on known retryable errors\n console.warn(\"retrying on proxy error\", err);\n lastErr = err;\n }\n }\n throw lastErr;\n}\n", - "transpiled": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */ import { parseNameVersion } from \"../util/registry_utils.ts\";\nexport const S3_BUCKET = \"http://deno-registry2-prod-storagebucket-b3a31d16.s3-website-us-east-1.amazonaws.com/\";\n/** Handle _legacy_ v1 registry requests. v2 is handled by `./suggestions.ts`.\n */ export async function handleRegistryRequest(url) {\n const entry = parsePathname(url.pathname);\n if (!entry) {\n return new Response(\"This module entry is invalid: \" + url.pathname, {\n status: 400,\n headers: {\n \"content-type\": \"text/plain\"\n }\n });\n }\n const { module , version , path } = entry;\n if (!version) {\n const latest = await getLatestVersion(module);\n if (!latest) {\n return new Response(\"This module has no latest version: \" + url.pathname, {\n status: 404,\n headers: {\n \"content-type\": \"text/plain\"\n }\n });\n }\n return new Response(undefined, {\n headers: {\n Location: `${module === \"std\" ? \"\" : \"/x\"}/${module}@${latest}/${path}`,\n \"x-deno-warning\": `Implicitly using latest version (${latest}) for ${url.origin}${module === \"std\" ? \"\" : \"/x\"}/${module}/${path}`\n },\n status: 302\n });\n }\n if (version.startsWith(\"v0.\") && module === \"std\") {\n const correctVersion = version.substring(1);\n const versionNumber = parseFloat(correctVersion);\n // For now only block std versions >= 0.43.0\n // Timeline for deprecation:\n // Oct 14 2020: >= 0.70.0\n // Oct 21 2020: >= 0.68.0\n // Oct 28 2020: >= 0.65.0\n // Nov 04 2020: >= 0.61.0\n // Nov 11 2020: >= 0.56.0\n // Nov 18 2020: >= 0.50.0\n // Nov 25 2020: >= 0.43.0\n // Dec 02 2020: >= 0.34.0 (oldest available std release)\n if (versionNumber >= 0.43) {\n return new Response(\"404 Not Found\", {\n headers: {\n \"x-deno-warning\": `std versions prefixed with 'v' were deprecated recently. Please change your import to ${url.origin}${module === \"std\" ? \"\" : \"/x\"}/${module}@${correctVersion}/${path} (at ${url.origin}${module === \"std\" ? \"\" : \"/x\"}/${module}@${version}/${path})`\n },\n status: 404\n });\n }\n return new Response(undefined, {\n headers: {\n Location: `/std@${correctVersion}/${path}`,\n \"x-deno-warning\": `std versions prefixed with 'v' will be deprecated soon. Please change your import to ${url.origin}${module === \"std\" ? \"\" : \"/x\"}/${module}@${correctVersion}/${path} (at ${url.origin}${module === \"std\" ? \"\" : \"/x\"}/${module}@${version}/${path})`\n },\n status: 302\n });\n }\n const remoteUrl = getBackingURL(module, version, path);\n const resp2 = await fetchSource(remoteUrl);\n // JSX and TSX content type fix\n if (remoteUrl.endsWith(\".jsx\") && !resp2.headers.get(\"content-type\")?.includes(\"javascript\")) {\n resp2.headers.set(\"content-type\", \"application/javascript\");\n } else if (remoteUrl.endsWith(\".tsx\") && !resp2.headers.get(\"content-type\")?.includes(\"typescript\")) {\n resp2.headers.set(\"content-type\", \"application/typescript\");\n }\n resp2.headers.set(\"Access-Control-Allow-Origin\", \"*\");\n return resp2;\n}\nexport function parsePathname(pathname) {\n if (pathname.startsWith(\"/std\")) {\n return parsePathname(\"/x\" + pathname);\n }\n if (!pathname.startsWith(\"/x/\")) {\n return undefined;\n }\n pathname = decodeURIComponent(pathname);\n const nameBranchRest = pathname.replace(/^\\/x\\//, \"\");\n const [nameBranch, ...rest] = nameBranchRest.split(\"/\");\n const [name, version] = parseNameVersion(nameBranch);\n const path = rest.join(\"/\");\n return {\n module: name,\n version,\n path\n };\n}\nexport function getBackingURL(module, version, path) {\n return `${S3_BUCKET}${module}/versions/${version}/raw/${path}`;\n}\nexport async function fetchSource(remoteUrl) {\n let lastErr;\n for(let i = 0; i < 3; i++){\n try {\n const resp = await fetch(remoteUrl);\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"404 Not Found\", {\n status: 404\n });\n }\n if (!resp.ok) throw new TypeError(\"non 2xx status code returned\");\n return new Response(resp.body, {\n headers: resp.headers,\n status: resp.status\n });\n } catch (err) {\n // TODO(lucacasonato): only retry on known retryable errors\n console.warn(\"retrying on proxy error\", err);\n lastErr = err;\n }\n }\n throw lastErr;\n}\nexport async function getLatestVersion(module) {\n let lastErr;\n for(let i = 0; i < 3; i++){\n try {\n const res = await fetch(`${S3_BUCKET}${module}/meta/versions.json`);\n if (res.status === 404 || res.status === 403) return undefined;\n if (!res.ok) throw new TypeError(\"non 2xx status code returned\");\n const versions = await res.json();\n return versions?.latest;\n } catch (err) {\n // TODO(lucacasonato): only retry on known retryable errors\n console.warn(\"retrying on proxy error\", err);\n lastErr = err;\n }\n }\n throw lastErr;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxmaWxlOi8vL3NyYy93b3JrZXIvcmVnaXN0cnkudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEVBQXdFLEFBQXhFLG9FQUF3RSxBQUF4RSxFQUF3RSxDQUV4RSxNQUFNLEdBQUcsZ0JBQWdCLFFBQVEsQ0FBMkI7QUFFNUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQ3BCLENBQXVGO0FBRXpGLEVBQ0csQUFESDtDQUNHLEFBREgsRUFDRyxDQUNILE1BQU0sZ0JBQWdCLHFCQUFxQixDQUFDLEdBQVEsRUFBcUIsQ0FBQztJQUN4RSxLQUFLLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUTtJQUN4QyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUM7UUFDWCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFnQyxrQ0FBRyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEUsTUFBTSxFQUFFLEdBQUc7WUFDWCxPQUFPLEVBQUUsQ0FBQztnQkFBQyxDQUFjLGVBQUUsQ0FBWTtZQUFDLENBQUM7UUFDM0MsQ0FBQztJQUNILENBQUM7SUFDRCxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRSxPQUFPLEdBQUUsSUFBSSxFQUFDLENBQUMsR0FBRyxLQUFLO0lBQ3ZDLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQztRQUNiLEtBQUssQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLGdCQUFnQixDQUFDLE1BQU07UUFDNUMsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO1lBQ1osTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQ2pCLENBQXFDLHVDQUFHLEdBQUcsQ0FBQyxRQUFRLEVBQ3BELENBQUM7Z0JBQ0MsTUFBTSxFQUFFLEdBQUc7Z0JBQ1gsT0FBTyxFQUFFLENBQUM7b0JBQUMsQ0FBYyxlQUFFLENBQVk7Z0JBQUMsQ0FBQztZQUMzQyxDQUFDO1FBRUwsQ0FBQztRQUNELE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFB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", - "content_type": null, - "deps": ["file:///src/util/registry_utils.ts"] - } - }, - "https://deno.land/std@0.108.0/async/deferred.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n// TODO(ry) It'd be better to make Deferred a class that inherits from\n// Promise, rather than an interface. This is possible in ES2016, however\n// typescript produces broken code when targeting ES5 code.\n// See https://github.com/Microsoft/TypeScript/issues/15202\n// At the time of writing, the github issue is closed but the problem remains.\nexport interface Deferred extends Promise {\n readonly state: \"pending\" | \"fulfilled\" | \"rejected\";\n resolve(value?: T | PromiseLike): void;\n // deno-lint-ignore no-explicit-any\n reject(reason?: any): void;\n}\n\n/** Creates a Promise with the `reject` and `resolve` functions\n * placed as methods on the promise object itself. It allows you to do:\n *\n * ```ts\n * import { deferred } from \"./deferred.ts\";\n *\n * const p = deferred();\n * // ...\n * p.resolve(42);\n * ```\n */\nexport function deferred(): Deferred {\n let methods;\n let state = \"pending\";\n const promise = new Promise((resolve, reject): void => {\n methods = {\n async resolve(value: T | PromiseLike) {\n await value;\n state = \"fulfilled\";\n resolve(value);\n },\n // deno-lint-ignore no-explicit-any\n reject(reason?: any) {\n state = \"rejected\";\n reject(reason);\n },\n };\n });\n Object.defineProperty(promise, \"state\", { get: () => state });\n return Object.assign(promise, methods) as Deferred;\n}\n", - "transpiled": "/** Creates a Promise with the `reject` and `resolve` functions\n * placed as methods on the promise object itself. It allows you to do:\n *\n * ```ts\n * import { deferred } from \"./deferred.ts\";\n *\n * const p = deferred();\n * // ...\n * p.resolve(42);\n * ```\n */ export function deferred() {\n let methods;\n let state = \"pending\";\n const promise = new Promise((resolve, reject)=>{\n methods = {\n async resolve (value) {\n await value;\n state = \"fulfilled\";\n resolve(value);\n },\n // deno-lint-ignore no-explicit-any\n reject (reason) {\n state = \"rejected\";\n reject(reason);\n }\n };\n });\n Object.defineProperty(promise, \"state\", {\n get: ()=>state\n });\n return Object.assign(promise, methods);\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy9kZWZlcnJlZC50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBYUEsRUFVRyxBQVZIOzs7Ozs7Ozs7O0NBVUcsQUFWSCxFQVVHLENBQ0gsTUFBTSxVQUFVLFFBQVEsR0FBbUIsQ0FBQztJQUMxQyxHQUFHLENBQUMsT0FBTztJQUNYLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBUztJQUNyQixLQUFLLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQUssT0FBTyxFQUFFLE1BQU0sR0FBVyxDQUFDO1FBQ3pELE9BQU8sR0FBRyxDQUFDO2tCQUNILE9BQU8sRUFBQyxLQUF5QixFQUFFLENBQUM7Z0JBQ3hDLEtBQUssQ0FBQyxLQUFLO2dCQUNYLEtBQUssR0FBRyxDQUFXO2dCQUNuQixPQUFPLENBQUMsS0FBSztZQUNmLENBQUM7WUFDRCxFQUFtQyxBQUFuQyxpQ0FBbUM7WUFDbkMsTUFBTSxFQUFDLE1BQVksRUFBRSxDQUFDO2dCQUNwQixLQUFLLEdBQUcsQ0FBVTtnQkFDbEIsTUFBTSxDQUFDLE1BQU07WUFDZixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFPLFFBQUUsQ0FBQztRQUFDLEdBQUcsTUFBUSxLQUFLO0lBQUMsQ0FBQztJQUM1RCxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsT0FBTztBQUN2QyxDQUFDIn0=", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.120.0/async/mux_async_iterator.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nimport { Deferred, deferred } from \"./deferred.ts\";\n\ninterface TaggedYieldedValue {\n iterator: AsyncIterator;\n value: T;\n}\n\n/** The MuxAsyncIterator class multiplexes multiple async iterators into a\n * single stream. It currently makes an assumption:\n * - The final result (the value returned and not yielded from the iterator)\n * does not matter; if there is any, it is discarded.\n */\nexport class MuxAsyncIterator implements AsyncIterable {\n private iteratorCount = 0;\n private yields: Array> = [];\n // deno-lint-ignore no-explicit-any\n private throws: any[] = [];\n private signal: Deferred = deferred();\n\n add(iterable: AsyncIterable): void {\n ++this.iteratorCount;\n this.callIteratorNext(iterable[Symbol.asyncIterator]());\n }\n\n private async callIteratorNext(\n iterator: AsyncIterator,\n ) {\n try {\n const { value, done } = await iterator.next();\n if (done) {\n --this.iteratorCount;\n } else {\n this.yields.push({ iterator, value });\n }\n } catch (e) {\n this.throws.push(e);\n }\n this.signal.resolve();\n }\n\n async *iterate(): AsyncIterableIterator {\n while (this.iteratorCount > 0) {\n // Sleep until any of the wrapped iterators yields.\n await this.signal;\n\n // Note that while we're looping over `yields`, new items may be added.\n for (let i = 0; i < this.yields.length; i++) {\n const { iterator, value } = this.yields[i];\n yield value;\n this.callIteratorNext(iterator);\n }\n\n if (this.throws.length) {\n for (const e of this.throws) {\n throw e;\n }\n this.throws.length = 0;\n }\n // Clear the `yields` list and reset the `signal` promise.\n this.yields.length = 0;\n this.signal = deferred();\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator {\n return this.iterate();\n }\n}\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nimport { deferred } from \"./deferred.ts\";\n/** The MuxAsyncIterator class multiplexes multiple async iterators into a\n * single stream. It currently makes an assumption:\n * - The final result (the value returned and not yielded from the iterator)\n * does not matter; if there is any, it is discarded.\n */ export class MuxAsyncIterator {\n iteratorCount = 0;\n yields = [];\n // deno-lint-ignore no-explicit-any\n throws = [];\n signal = deferred();\n add(iterable) {\n ++this.iteratorCount;\n this.callIteratorNext(iterable[Symbol.asyncIterator]());\n }\n async callIteratorNext(iterator) {\n try {\n const { value , done } = await iterator.next();\n if (done) {\n --this.iteratorCount;\n } else {\n this.yields.push({\n iterator,\n value\n });\n }\n } catch (e) {\n this.throws.push(e);\n }\n this.signal.resolve();\n }\n async *iterate() {\n while(this.iteratorCount > 0){\n // Sleep until any of the wrapped iterators yields.\n await this.signal;\n // Note that while we're looping over `yields`, new items may be added.\n for(let i = 0; i < this.yields.length; i++){\n const { iterator , value } = this.yields[i];\n yield value;\n this.callIteratorNext(iterator);\n }\n if (this.throws.length) {\n for (const e of this.throws){\n throw e;\n }\n this.throws.length = 0;\n }\n // Clear the `yields` list and reset the `signal` promise.\n this.yields.length = 0;\n this.signal = deferred();\n }\n }\n [Symbol.asyncIterator]() {\n return this.iterate();\n }\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy9tdXhfYXN5bmNfaXRlcmF0b3IudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEVBQTBFLEFBQTFFLHdFQUEwRTtBQUMxRSxNQUFNLEdBQWEsUUFBUSxRQUFRLENBQWU7QUFPbEQsRUFJRyxBQUpIOzs7O0NBSUcsQUFKSCxFQUlHLENBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQUNuQixhQUFhLEdBQUcsQ0FBQztJQUNqQixNQUFNLEdBQWlDLENBQUMsQ0FBQztJQUNqRCxFQUFtQyxBQUFuQyxpQ0FBbUM7SUFDM0IsTUFBTSxHQUFVLENBQUMsQ0FBQztJQUNsQixNQUFNLEdBQW1CLFFBQVE7SUFFekMsR0FBRyxDQUFDLFFBQTBCLEVBQVEsQ0FBQztVQUNuQyxJQUFJLENBQUMsYUFBYTtRQUNwQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxhQUFhO0lBQ3JELENBQUM7VUFFYSxnQkFBZ0IsQ0FDNUIsUUFBMEIsRUFDMUIsQ0FBQztRQUNELEdBQUcsQ0FBQyxDQUFDO1lBQ0gsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUUsSUFBSSxFQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUk7WUFDM0MsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDO2tCQUNQLElBQUksQ0FBQyxhQUFhO1lBQ3RCLENBQUMsTUFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQUMsUUFBUTtvQkFBRSxLQUFLO2dCQUFDLENBQUM7WUFDdEMsQ0FBQztRQUNILENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BCLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU87SUFDckIsQ0FBQztXQUVNLE9BQU8sR0FBNkIsQ0FBQztjQUNuQyxJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBRSxDQUFDO1lBQzlCLEVBQW1ELEFBQW5ELGlEQUFtRDtZQUNuRCxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU07WUFFakIsRUFBdUUsQUFBdkUscUVBQXVFO1lBQ3ZFLEdBQUcsQ0FBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFJLENBQUM7Z0JBQzVDLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxHQUFFLEtBQUssRUFBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO3NCQUNuQyxLQUFLO2dCQUNYLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRO1lBQ2hDLENBQUM7WUFFRCxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDdkIsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBRSxDQUFDO29CQUM1QixLQUFLLENBQUMsQ0FBQztnQkFDVCxDQUFDO2dCQUNELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7WUFDeEIsQ0FBQztZQUNELEVBQTBELEFBQTFELHdEQUEwRDtZQUMxRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDO1lBQ3RCLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUTtRQUN4QixDQUFDO0lBQ0gsQ0FBQztLQUVBLE1BQU0sQ0FBQyxhQUFhLElBQXNCLENBQUM7UUFDMUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPO0lBQ3JCLENBQUMifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/std@0.120.0/async/deferred.ts"] - } - }, - "file:///src/worker/handler.ts": { - "Source": { - "source": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */\n\nimport { handleRegistryRequest } from \"./registry.ts\";\nimport { handleConfigRequest } from \"./registry_config.ts\";\nimport { handleApiRequest } from \"./suggestions.ts\";\nimport { handleVSCRequest } from \"./vscode.ts\";\n\nimport type { ConnInfo } from \"https://deno.land/std@0.112.0/http/server.ts\";\nimport { createReporter } from \"https://deno.land/x/g_a@0.1.2/mod.ts\";\nimport { accepts } from \"https://deno.land/x/oak_commons@0.1.1/negotiation.ts\";\n\nconst REMOTE_URL = \"https://deno-website2.now.sh\";\n\nconst ga = createReporter({\n filter(req, res) {\n const { pathname } = new URL(req.url);\n const isHtml = accepts(req, \"application/*\", \"text/html\") === \"text/html\";\n return pathname === \"/\" || pathname.startsWith(\"/std\") ||\n pathname.startsWith(\"/x\") || isHtml || res.status >= 400;\n },\n metaData(req, res) {\n const accept = req.headers.get(\"accept\");\n const referer = req.headers.get(\"referer\");\n const userAgent = req.headers.get(\"user-agent\");\n\n const { ok, statusText } = res;\n const isHtml = accepts(req, \"application/*\", \"text/html\") === \"text/html\";\n\n // Set the page title to \"website\" or \"javascript\" or \"typescript\" or \"wasm\"\n const contentType = res.headers.get(\"content-type\");\n let documentTitle;\n if (!ok) {\n documentTitle = statusText.toLowerCase();\n } else if (isHtml) {\n documentTitle = \"website\";\n } else if (contentType != null) {\n documentTitle = /^application\\/(.*?)(?:;|$)/i.exec(contentType)?.[1];\n }\n\n // Files downloaded by a bot (deno, curl) get a special medium/source tag.\n let campaignMedium;\n let campaignSource;\n if (\n referer == null &&\n (userAgent == null || !userAgent.startsWith(\"Mozilla/\")) &&\n (accept == null || accept === \"*/*\")\n ) {\n campaignMedium = \"Bot\";\n campaignSource = userAgent?.replace(/[^\\w\\-].*$/, \"\");\n }\n\n return { campaignMedium, campaignSource, documentTitle };\n },\n});\n\nexport function withLog(\n handler: (\n request: Request,\n connInfo: ConnInfo,\n ) => Response | Promise,\n): (request: Request, connInfo: ConnInfo) => Promise {\n return async (req, con) => {\n let err: unknown;\n let res!: Response;\n const start = performance.now();\n try {\n res = await handler(req, con);\n } catch (e) {\n err = e;\n console.error(err);\n res = new Response(\n \"500 Internal Server Error\\nPlease try again later.\",\n { status: 500 },\n );\n } finally {\n await ga(req, con, res, start, err);\n }\n return res;\n };\n}\n\nexport function handleRequest(request: Request): Promise {\n // this checks to see if the requestor prefers \"application\" code over \"html\"\n // which would be run-time clients who either omit an accept header (which\n // implies any content type) or provides a `*/*` header\n const isHtml = accepts(request, \"application/*\", \"text/html\") === \"text/html\";\n\n const url = new URL(request.url);\n\n if (url.pathname === \"/v1\") {\n return Promise.resolve(\n Response.redirect(\"https://deno.land/posts/v1\", 301),\n );\n }\n\n if (url.pathname === \"/posts\") {\n return Promise.resolve(Response.redirect(\"https://deno.com/blog\", 307));\n }\n\n if (url.pathname.startsWith(\"/posts/\")) {\n return Promise.resolve(Response.redirect(\n `https://deno.com/blog/${url.pathname.substring(\"/posts/\".length)}`,\n 307,\n ));\n }\n\n if (url.pathname.startsWith(\"/typedoc\")) {\n return Promise.resolve(\n Response.redirect(\"https://doc.deno.land/deno/stable\", 301),\n );\n }\n\n if (url.pathname.startsWith(\"/_vsc\")) {\n return handleVSCRequest(url);\n }\n\n if (url.pathname.startsWith(\"/_api/\")) {\n return handleApiRequest(url);\n }\n\n if ([\"/install.sh\", \"/install.ps1\"].includes(url.pathname)) {\n return Promise.resolve(\n Response.redirect(`https://deno.land/x/install${url.pathname}`, 307),\n );\n }\n\n if (url.pathname === \"/.well-known/deno-import-intellisense.json\") {\n return handleConfigRequest(request);\n }\n\n const isRegistryRequest = url.pathname.startsWith(\"/std\") ||\n url.pathname.startsWith(\"/x/\");\n\n if (isRegistryRequest) {\n if (isHtml) {\n const ln = extractAltLineNumberReference(url.toString());\n if (ln) {\n return Promise.resolve(\n Response.redirect(`${ln.rest}#L${ln.line}`, 302),\n );\n }\n } else {\n return handleRegistryRequest(url);\n }\n }\n\n if (![\"HEAD\", \"GET\"].includes(request.method)) {\n return Promise.resolve(new Response(null, { status: 405 })); // Method not allowed.\n }\n\n return proxyFile(url, REMOTE_URL, request);\n}\n\nconst ALT_LINENUMBER_MATCHER = /(.*):(\\d+):\\d+$/;\n\nexport function extractAltLineNumberReference(\n url: string,\n): { rest: string; line: number } | null {\n const matches = ALT_LINENUMBER_MATCHER.exec(url);\n if (matches === null) return null;\n return {\n rest: matches[1],\n line: parseInt(matches[2]),\n };\n}\n\ninterface CacheEntry {\n body: ArrayBuffer;\n contentType: string;\n etag: string;\n immutable: boolean;\n}\n\nconst cache = new Map();\n\n// When deploying a new version, the worker will be updated before the static\n// website hosted by Vercel gets updated. Therefore we clear the cache 2 minutes\n// after startup up to ensure that there is no stale static content in the\n// in-memory cache.\nsetTimeout(() => cache.clear(), 2 * 60 * 1000);\n\nasync function proxyFile(\n url: URL,\n remoteUrl: string,\n request: Request,\n): Promise {\n const proxyUrl = new URL(remoteUrl + url.pathname).href;\n let cacheEntry = cache.get(proxyUrl);\n\n if (cacheEntry === undefined) {\n const proxyRequest = new Request(proxyUrl);\n const proxyResponse = await fetchWithRetry(proxyRequest);\n\n if (!(proxyResponse.ok || proxyResponse.redirected)) {\n return proxyResponse;\n }\n\n const body = await proxyResponse.arrayBuffer();\n const contentType = proxyResponse.headers.get(\"content-type\") ??\n \"application/binary\";\n const etag = await crypto.subtle.digest(\"SHA-1\", body).then((hash) =>\n Array.from(new Uint8Array(hash))\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")\n );\n const immutable = /\\bimmutable\\b/i\n .test(proxyResponse.headers.get(\"cache-control\") ?? \"\");\n\n cacheEntry = {\n body,\n contentType,\n etag,\n immutable,\n };\n cache.set(proxyUrl, cacheEntry);\n }\n\n if (request.headers.get(\"if-none-match\") !== cacheEntry.etag) {\n let body;\n switch (request.method) {\n case \"HEAD\":\n body = null;\n break;\n case \"GET\":\n body = cacheEntry.body;\n break;\n default:\n throw new Error(`Unsupported request method: ${request.method}`);\n }\n return new Response(body, {\n headers: {\n \"content-type\": cacheEntry.contentType,\n \"cache-control\": cacheEntry.immutable\n ? \"public,max-age=31536000,immutable\"\n : \"public,max-age=0,must-revalidate\",\n \"etag\": cacheEntry.etag,\n },\n });\n } else {\n return new Response(null, { status: 304 }); // Not modified.\n }\n}\n\nasync function fetchWithRetry(request: Request): Promise {\n let promise: Promise;\n for (let i = 0; i < 3; i++) {\n promise = fetch(request);\n try {\n return await promise;\n } catch (err) {\n // TODO(lucacasonato): only retry on known retryable errors\n console.warn(\"retrying on proxy error\", err);\n }\n }\n return promise!;\n}\n", - "transpiled": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */ import { handleRegistryRequest } from \"./registry.ts\";\nimport { handleConfigRequest } from \"./registry_config.ts\";\nimport { handleApiRequest } from \"./suggestions.ts\";\nimport { handleVSCRequest } from \"./vscode.ts\";\nimport { createReporter } from \"https://deno.land/x/g_a@0.1.2/mod.ts\";\nimport { accepts } from \"https://deno.land/x/oak_commons@0.1.1/negotiation.ts\";\nconst REMOTE_URL = \"https://deno-website2.now.sh\";\nconst ga = createReporter({\n filter (req, res) {\n const { pathname } = new URL(req.url);\n const isHtml = accepts(req, \"application/*\", \"text/html\") === \"text/html\";\n return pathname === \"/\" || pathname.startsWith(\"/std\") || pathname.startsWith(\"/x\") || isHtml || res.status >= 400;\n },\n metaData (req, res) {\n const accept = req.headers.get(\"accept\");\n const referer = req.headers.get(\"referer\");\n const userAgent = req.headers.get(\"user-agent\");\n const { ok , statusText } = res;\n const isHtml = accepts(req, \"application/*\", \"text/html\") === \"text/html\";\n // Set the page title to \"website\" or \"javascript\" or \"typescript\" or \"wasm\"\n const contentType = res.headers.get(\"content-type\");\n let documentTitle;\n if (!ok) {\n documentTitle = statusText.toLowerCase();\n } else if (isHtml) {\n documentTitle = \"website\";\n } else if (contentType != null) {\n documentTitle = /^application\\/(.*?)(?:;|$)/i.exec(contentType)?.[1];\n }\n // Files downloaded by a bot (deno, curl) get a special medium/source tag.\n let campaignMedium;\n let campaignSource;\n if (referer == null && (userAgent == null || !userAgent.startsWith(\"Mozilla/\")) && (accept == null || accept === \"*/*\")) {\n campaignMedium = \"Bot\";\n campaignSource = userAgent?.replace(/[^\\w\\-].*$/, \"\");\n }\n return {\n campaignMedium,\n campaignSource,\n documentTitle\n };\n }\n});\nexport function withLog(handler) {\n return async (req, con)=>{\n let err;\n let res;\n const start = performance.now();\n try {\n res = await handler(req, con);\n } catch (e) {\n err = e;\n console.error(err);\n res = new Response(\"500 Internal Server Error\\nPlease try again later.\", {\n status: 500\n });\n } finally{\n await ga(req, con, res, start, err);\n }\n return res;\n };\n}\nexport function handleRequest(request) {\n // this checks to see if the requestor prefers \"application\" code over \"html\"\n // which would be run-time clients who either omit an accept header (which\n // implies any content type) or provides a `*/*` header\n const isHtml = accepts(request, \"application/*\", \"text/html\") === \"text/html\";\n const url = new URL(request.url);\n if (url.pathname === \"/v1\") {\n return Promise.resolve(Response.redirect(\"https://deno.land/posts/v1\", 301));\n }\n if (url.pathname === \"/posts\") {\n return Promise.resolve(Response.redirect(\"https://deno.com/blog\", 307));\n }\n if (url.pathname.startsWith(\"/posts/\")) {\n return Promise.resolve(Response.redirect(`https://deno.com/blog/${url.pathname.substring(\"/posts/\".length)}`, 307));\n }\n if (url.pathname.startsWith(\"/typedoc\")) {\n return Promise.resolve(Response.redirect(\"https://doc.deno.land/deno/stable\", 301));\n }\n if (url.pathname.startsWith(\"/_vsc\")) {\n return handleVSCRequest(url);\n }\n if (url.pathname.startsWith(\"/_api/\")) {\n return handleApiRequest(url);\n }\n if ([\n \"/install.sh\",\n \"/install.ps1\"\n ].includes(url.pathname)) {\n return Promise.resolve(Response.redirect(`https://deno.land/x/install${url.pathname}`, 307));\n }\n if (url.pathname === \"/.well-known/deno-import-intellisense.json\") {\n return handleConfigRequest(request);\n }\n const isRegistryRequest = url.pathname.startsWith(\"/std\") || url.pathname.startsWith(\"/x/\");\n if (isRegistryRequest) {\n if (isHtml) {\n const ln = extractAltLineNumberReference(url.toString());\n if (ln) {\n return Promise.resolve(Response.redirect(`${ln.rest}#L${ln.line}`, 302));\n }\n } else {\n return handleRegistryRequest(url);\n }\n }\n if (![\n \"HEAD\",\n \"GET\"\n ].includes(request.method)) {\n return Promise.resolve(new Response(null, {\n status: 405\n })); // Method not allowed.\n }\n return proxyFile(url, REMOTE_URL, request);\n}\nconst ALT_LINENUMBER_MATCHER = /(.*):(\\d+):\\d+$/;\nexport function extractAltLineNumberReference(url) {\n const matches = ALT_LINENUMBER_MATCHER.exec(url);\n if (matches === null) return null;\n return {\n rest: matches[1],\n line: parseInt(matches[2])\n };\n}\nconst cache = new Map();\n// When deploying a new version, the worker will be updated before the static\n// website hosted by Vercel gets updated. Therefore we clear the cache 2 minutes\n// after startup up to ensure that there is no stale static content in the\n// in-memory cache.\nsetTimeout(()=>cache.clear()\n, 2 * 60 * 1000);\nasync function proxyFile(url, remoteUrl, request) {\n const proxyUrl = new URL(remoteUrl + url.pathname).href;\n let cacheEntry = cache.get(proxyUrl);\n if (cacheEntry === undefined) {\n const proxyRequest = new Request(proxyUrl);\n const proxyResponse = await fetchWithRetry(proxyRequest);\n if (!(proxyResponse.ok || proxyResponse.redirected)) {\n return proxyResponse;\n }\n const body = await proxyResponse.arrayBuffer();\n const contentType = proxyResponse.headers.get(\"content-type\") ?? \"application/binary\";\n const etag = await crypto.subtle.digest(\"SHA-1\", body).then((hash)=>Array.from(new Uint8Array(hash)).map((byte)=>byte.toString(16).padStart(2, \"0\")\n ).join(\"\")\n );\n const immutable = /\\bimmutable\\b/i.test(proxyResponse.headers.get(\"cache-control\") ?? \"\");\n cacheEntry = {\n body,\n contentType,\n etag,\n immutable\n };\n cache.set(proxyUrl, cacheEntry);\n }\n if (request.headers.get(\"if-none-match\") !== cacheEntry.etag) {\n let body;\n switch(request.method){\n case \"HEAD\":\n body = null;\n break;\n case \"GET\":\n body = cacheEntry.body;\n break;\n default:\n throw new Error(`Unsupported request method: ${request.method}`);\n }\n return new Response(body, {\n headers: {\n \"content-type\": cacheEntry.contentType,\n \"cache-control\": cacheEntry.immutable ? \"public,max-age=31536000,immutable\" : \"public,max-age=0,must-revalidate\",\n \"etag\": cacheEntry.etag\n }\n });\n } else {\n return new Response(null, {\n status: 304\n }); // Not modified.\n }\n}\nasync function fetchWithRetry(request) {\n let promise;\n for(let i = 0; i < 3; i++){\n promise = fetch(request);\n try {\n return await promise;\n } catch (err) {\n // TODO(lucacasonato): only retry on known retryable errors\n console.warn(\"retrying on proxy error\", err);\n }\n }\n return promise;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxmaWxlOi8vL3NyYy93b3JrZXIvaGFuZGxlci50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsRUFBd0UsQUFBeEUsb0VBQXdFLEFBQXhFLEVBQXdFLENBRXhFLE1BQU0sR0FBRyxxQkFBcUIsUUFBUSxDQUFlO0FBQ3JELE1BQU0sR0FBRyxtQkFBbUIsUUFBUSxDQUFzQjtBQUMxRCxNQUFNLEdBQUcsZ0JBQWdCLFFBQVEsQ0FBa0I7QUFDbkQsTUFBTSxHQUFHLGdCQUFnQixRQUFRLENBQWE7QUFHOUMsTUFBTSxHQUFHLGNBQWMsUUFBUSxDQUFzQztBQUNyRSxNQUFNLEdBQUcsT0FBTyxRQUFRLENBQXNEO0FBRTlFLEtBQUssQ0FBQyxVQUFVLEdBQUcsQ0FBOEI7QUFFakQsS0FBSyxDQUFDLEVBQUUsR0FBRyxjQUFjLENBQUMsQ0FBQztJQUN6QixNQUFNLEVBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHO1FBQ3BDLEtBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFlLGdCQUFFLENBQVcsZ0JBQU0sQ0FBVztRQUN6RSxNQUFNLENBQUMsUUFBUSxLQUFLLENBQUcsTUFBSSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQU0sVUFDbkQsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFJLFFBQUssTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLElBQUksR0FBRztJQUM1RCxDQUFDO0lBQ0QsUUFBUSxFQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUNsQixLQUFLLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQVE7UUFDdkMsS0FBSyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFTO1FBQ3pDLEtBQUss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", - "content_type": null, - "deps": [ - "file:///src/worker/registry.ts", - "file:///src/worker/registry_config.ts", - "file:///src/worker/suggestions.ts", - "file:///src/worker/vscode.ts", - "https://deno.land/x/g_a@0.1.2/mod.ts", - "https://deno.land/x/oak_commons@0.1.1/negotiation.ts" - ] - } - }, - "https://deno.land/std@0.108.0/async/tee.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n// Utility for representing n-tuple\ntype Tuple = N extends N\n ? number extends N ? T[] : TupleOf\n : never;\ntype TupleOf = R[\"length\"] extends N\n ? R\n : TupleOf;\n\nconst noop = () => {};\n\nclass AsyncIterableClone implements AsyncIterable {\n currentPromise: Promise>;\n resolveCurrent: (x: Promise>) => void = noop;\n consumed: Promise;\n consume: () => void = noop;\n\n constructor() {\n this.currentPromise = new Promise>((resolve) => {\n this.resolveCurrent = resolve;\n });\n this.consumed = new Promise((resolve) => {\n this.consume = resolve;\n });\n }\n\n reset() {\n this.currentPromise = new Promise>((resolve) => {\n this.resolveCurrent = resolve;\n });\n this.consumed = new Promise((resolve) => {\n this.consume = resolve;\n });\n }\n\n async next(): Promise> {\n const res = await this.currentPromise;\n this.consume();\n this.reset();\n return res;\n }\n\n async push(res: Promise>): Promise {\n this.resolveCurrent(res);\n // Wait until current promise is consumed and next item is requested.\n await this.consumed;\n }\n\n [Symbol.asyncIterator](): AsyncIterator {\n return this;\n }\n}\n\n/**\n * Branches the given async iterable into the n branches.\n *\n * Example:\n *\n * ```ts\n * import { tee } from \"./tee.ts\";\n *\n * const gen = async function* gen() {\n * yield 1;\n * yield 2;\n * yield 3;\n * }\n *\n * const [branch1, branch2] = tee(gen());\n *\n * (async () => {\n * for await (const n of branch1) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n *\n * (async () => {\n * for await (const n of branch2) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n * ```\n */\nexport function tee(\n src: AsyncIterable,\n n: N = 2 as N,\n): Tuple, N> {\n const clones: Tuple, N> = Array.from({ length: n }).map(\n () => new AsyncIterableClone(),\n // deno-lint-ignore no-explicit-any\n ) as any;\n (async () => {\n const iter = src[Symbol.asyncIterator]();\n await Promise.resolve();\n while (true) {\n const res = iter.next();\n await Promise.all(clones.map((c) => c.push(res)));\n if ((await res).done) {\n break;\n }\n }\n })().catch((e) => {\n console.error(e);\n });\n return clones;\n}\n", - "transpiled": "const noop = ()=>{\n};\nclass AsyncIterableClone {\n currentPromise;\n resolveCurrent = noop;\n consumed;\n consume = noop;\n constructor(){\n this.currentPromise = new Promise((resolve)=>{\n this.resolveCurrent = resolve;\n });\n this.consumed = new Promise((resolve)=>{\n this.consume = resolve;\n });\n }\n reset() {\n this.currentPromise = new Promise((resolve)=>{\n this.resolveCurrent = resolve;\n });\n this.consumed = new Promise((resolve)=>{\n this.consume = resolve;\n });\n }\n async next() {\n const res = await this.currentPromise;\n this.consume();\n this.reset();\n return res;\n }\n async push(res) {\n this.resolveCurrent(res);\n // Wait until current promise is consumed and next item is requested.\n await this.consumed;\n }\n [Symbol.asyncIterator]() {\n return this;\n }\n}\n/**\n * Branches the given async iterable into the n branches.\n *\n * Example:\n *\n * ```ts\n * import { tee } from \"./tee.ts\";\n *\n * const gen = async function* gen() {\n * yield 1;\n * yield 2;\n * yield 3;\n * }\n *\n * const [branch1, branch2] = tee(gen());\n *\n * (async () => {\n * for await (const n of branch1) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n *\n * (async () => {\n * for await (const n of branch2) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n * ```\n */ export function tee(src, n = 2) {\n const clones = Array.from({\n length: n\n }).map(()=>new AsyncIterableClone()\n );\n (async ()=>{\n const iter = src[Symbol.asyncIterator]();\n await Promise.resolve();\n while(true){\n const res = iter.next();\n await Promise.all(clones.map((c)=>c.push(res)\n ));\n if ((await res).done) {\n break;\n }\n }\n })().catch((e)=>{\n console.error(e);\n });\n return clones;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy90ZWUudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVVBLEtBQUssQ0FBQyxJQUFJLE9BQVMsQ0FBQztBQUFBLENBQUM7TUFFZixrQkFBa0I7SUFDdEIsY0FBYztJQUNkLGNBQWMsR0FBNEMsSUFBSTtJQUM5RCxRQUFRO0lBQ1IsT0FBTyxHQUFlLElBQUk7aUJBRVosQ0FBQztRQUNiLElBQUksQ0FBQyxjQUFjLEdBQUcsR0FBRyxDQUFDLE9BQU8sRUFBcUIsT0FBTyxHQUFLLENBQUM7WUFDakUsSUFBSSxDQUFDLGNBQWMsR0FBRyxPQUFPO1FBQy9CLENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQVEsT0FBTyxHQUFLLENBQUM7WUFDOUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPO1FBQ3hCLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxHQUFHLENBQUM7UUFDUCxJQUFJLENBQUMsY0FBYyxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQXFCLE9BQU8sR0FBSyxDQUFDO1lBQ2pFLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTztRQUMvQixDQUFDO1FBQ0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsT0FBTyxFQUFRLE9BQU8sR0FBSyxDQUFDO1lBQzlDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTztRQUN4QixDQUFDO0lBQ0gsQ0FBQztVQUVLLElBQUksR0FBK0IsQ0FBQztRQUN4QyxLQUFLLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYztRQUNyQyxJQUFJLENBQUMsT0FBTztRQUNaLElBQUksQ0FBQyxLQUFLO1FBQ1YsTUFBTSxDQUFDLEdBQUc7SUFDWixDQUFDO1VBRUssSUFBSSxDQUFDLEdBQStCLEVBQWlCLENBQUM7UUFDMUQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHO1FBQ3ZCLEVBQXFFLEFBQXJFLG1FQUFxRTtRQUNyRSxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVE7SUFDckIsQ0FBQztLQUVBLE1BQU0sQ0FBQyxhQUFhLElBQXNCLENBQUM7UUFDMUMsTUFBTSxDQUFDLElBQUk7SUFDYixDQUFDOztBQUdILEVBNEJHLEFBNUJIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBNEJHLEFBNUJILEVBNEJHLENBQ0gsTUFBTSxVQUFVLEdBQUcsQ0FDakIsR0FBcUIsRUFDckIsQ0FBSSxHQUFHLENBQUMsRUFDb0IsQ0FBQztJQUM3QixLQUFLLENBQUMsTUFBTSxHQUFvQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFBQyxNQUFNLEVBQUUsQ0FBQztJQUFDLENBQUMsRUFBRSxHQUFHLEtBQ3JFLEdBQUcsQ0FBQyxrQkFBa0I7O2VBR2pCLENBQUM7UUFDWixLQUFLLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYTtRQUNyQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU87Y0FDZCxJQUFJLENBQUUsQ0FBQztZQUNaLEtBQUssQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUk7WUFDckIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHOztZQUM5QyxFQUFFLEdBQUcsS0FBSyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQztnQkFDckIsS0FBSztZQUNQLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQyxJQUFJLEtBQUssRUFBRSxDQUFDLEdBQUssQ0FBQztRQUNqQixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakIsQ0FBQztJQUNELE1BQU0sQ0FBQyxNQUFNO0FBQ2YsQ0FBQyJ9", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/x/g_a@0.1.2/mod.ts": { - "Source": { - "source": "// Copyright 2021-2022 the Deno authors. All rights reserved. MIT license.\n\nimport { delay } from \"https://deno.land/std@0.120.0/async/mod.ts\";\nimport * as colors from \"https://deno.land/std@0.120.0/fmt/colors.ts\";\nimport { STATUS_TEXT } from \"https://deno.land/std@0.120.0/http/http_status.ts\";\nimport type { Context } from \"https://deno.land/x/oak@v10.1.0/context.ts\";\nimport type { Middleware } from \"https://deno.land/x/oak@v10.1.0/middleware.ts\";\n\nconst GA_TRACKING_ID = \"GA_TRACKING_ID\";\nconst GA_BATCH_ENDPOINT = \"https://www.google-analytics.com/batch\";\nconst GA_MAX_PARAM_LENGTH = 2_048; // 2kb\nconst GA_MAX_PAYLOAD_LENGTH = 8_092; // 8kb\nconst GA_MAX_BATCH_PAYLOAD_COUNT = 20;\nconst GA_MAX_BATCH_LENGTH = 16_386; // 16kb\nconst UPLOAD_DELAY = 1_000;\nconst SLOW_UPLOAD_THRESHOLD = 1_000;\n\n/** A narrowed down version of `Deno.Conn` which only contains the information\n * which the library usages. */\nexport interface Conn {\n readonly remoteAddr: Deno.Addr;\n}\n\n/** The shape of the Google Analytics measurement that is supported.\n *\n * Ref: https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters\n */\ninterface GAMeasurement {\n v: 1;\n tid: string;\n t:\n | \"pageview\"\n | \"screenview\"\n | \"event\"\n | \"transaction\"\n | \"item\"\n | \"social\"\n | \"exception\"\n | \"timing\";\n cid: string;\n uip: string;\n dl: string;\n dt?: string;\n dr?: string | null;\n cm?: string;\n cs?: string;\n ua?: string | null;\n exd?: string;\n exf: boolean;\n srt: number;\n qt: number;\n}\n\n/** Specialized data fields that are supported being set via a callback. */\nexport interface MetaData {\n /** The value to be assigned to the `cm` field in the measurement payload. */\n campaignMedium?: string;\n /** The value to be assigned to the `cs` field in the measurement payload. */\n campaignSource?: string;\n /** The value to be assigned to the `dt` field in the measurement payload. */\n documentTitle?: string;\n}\n\n/** The interface returned from `createReporter()` that is then called to\n * enqueue measurement messages to be sent to Google Analytics. */\nexport interface Reporter {\n /**\n * A reporter function which will asynchronously dispatch measurement messages\n * to Google Analytics.\n *\n * @param req the web standard request received\n * @param conn the connection information of the request\n * @param res the web standard response being sent\n * @param start the time in milliseconds when the request started being\n * handled\n * @param error any error associated with handling the request/response\n * @returns a promise that resolves when the measurement is enqueued to be\n * sent to Google Analytics.\n */\n (\n req: Request,\n conn: Conn,\n res: Response,\n start: number,\n error?: unknown,\n ): Promise;\n}\n\n/** Options which can be supplied to the `createReporter()` factory function. */\nexport interface ReporterOptions {\n /** The batch Google Analytics endpoint to send messages to. This defaults\n * to `https://www.google-analytics.com/batch`. */\n endpoint?: string;\n /** An optional callback which determines if a particular request should\n * generate a measurement message.\n *\n * @param req the current `Request` object.\n * @param res the current `Response` object.\n * @returns `true` if the request should generate a measurement, or `false`.\n */\n filter?(req: Request, res: Response): boolean;\n /** The Google Analytics web property ID. This defaults to being read from the\n * `GA_TRACKING_ID` environment variable. If neither the property ID is passed\n * nor is the environment variable set, dispatching will be disabled. */\n id?: string;\n /** An optional function/method for logging warning messages generated from\n * the library. This defaults to logging to `console.warn()`. */\n log?(msg: string): void;\n /** An optional callback which provides optional data to enrich the\n * measurement message.\n *\n * @param req the current `Request` object.\n * @param res the current `Response` object.\n * @returns The meta data to enrich the measurement, or `undefined`.\n */\n metaData?(req: Request, res: Response): MetaData | undefined;\n /** A boolean which defaults to `true` that indicates if the library should\n * log warning messages or not. */\n warn?: boolean;\n}\n\n/** Options which can be supplied to the `createReporterMiddleware()` factory\n * function. */\nexport interface ReportMiddlewareOptions {\n /** The batch Google Analytics endpoint to send messages to. This defaults\n * to `https://www.google-analytics.com/batch`. */\n endpoint?: string;\n /** An optional callback which determines if a particular request should\n * generate a measurement message.\n *\n * @param ctx the context related to the request/response being processed\n * @returns `true` if the request should generate a measurement, or `false`.\n */\n filter?(ctx: Context): boolean;\n /** The Google Analytics web property ID. This defaults to being read from the\n * `GA_TRACKING_ID` environment variable. If neither the property ID is passed\n * nor is the environment variable set, dispatching will be disabled. */\n id?: string;\n /** An optional function/method for logging warning messages generated from\n * the library. This defaults to logging to `console.warn()`. */\n log?(msg: string): void;\n /** An optional callback which provides optional data to enrich the\n * measurement message.\n *\n * @param ctx the context related to the request/response being processed\n * @returns The meta data to enrich the measurement, or `undefined`.\n */\n metaData?(ctx: Context): MetaData | undefined;\n /** A boolean which defaults to `true` that indicates if the library should\n * log warning messages or not. */\n warn?: boolean;\n}\n\nconst encoder = new TextEncoder();\nconst batch = new Uint8Array(GA_MAX_BATCH_LENGTH);\nconst queue: Uint8Array[] = [];\nlet uploading = false;\n\n/** Create a queue that dispatches queued messages to the endpoint, returning\n * the enqueue function. */\nfunction createEnqueue(\n endpoint: string,\n log: (msg: string) => void,\n warn: boolean,\n) {\n async function upload() {\n while (queue.length) {\n let count = 0;\n let length = 0;\n while (count < Math.min(queue.length, GA_MAX_BATCH_PAYLOAD_COUNT)) {\n const payload = queue[count];\n if (length + payload.length > GA_MAX_BATCH_LENGTH) {\n break;\n }\n batch.set(payload, length);\n count += 1;\n length += payload.length;\n }\n const body = batch.subarray(0, length);\n\n try {\n const start = performance.now();\n const res = await fetch(endpoint, { method: \"POST\", body });\n const duration = performance.now() - start;\n\n if ((res.status !== 200 || duration >= SLOW_UPLOAD_THRESHOLD) && warn) {\n log(\n `batch uploaded ${count} items in ${duration}ms. Response: ${res.status} ${res.statusText}`,\n );\n }\n\n // Google says not to retry when it reports a non-200 status code.\n queue.splice(0, count);\n } catch (err) {\n if (warn) {\n log(`batch upload failed: ${err}`);\n }\n await delay(UPLOAD_DELAY);\n }\n }\n uploading = false;\n }\n\n return function enqueue(payload: Uint8Array) {\n queue.push(payload);\n\n if (!uploading) {\n uploading = true;\n setTimeout(upload, UPLOAD_DELAY);\n }\n };\n}\n\nfunction defaultLog(msg: string) {\n console.warn(`[ga] ${colors.yellow(\"warn\")}: ${msg}`);\n}\n\n/** Create a SHA-1 hex string digest of the supplied message. */\nasync function toDigest(msg: string): Promise {\n const buffer = await crypto.subtle.digest(\"SHA-1\", encoder.encode(msg));\n return Array.from(new Uint8Array(buffer)).map((b) =>\n b.toString(16).padStart(2, \"0\")\n ).join(\"\");\n}\n\n/** Convert a Google Analytics message into a Uint8Array. */\nfunction toPayload(message: GAMeasurement): Uint8Array {\n const entries = Object.entries(message).filter(([, v]) => v).map((\n [k, v],\n ) => [k, String(v).slice(0, GA_MAX_PARAM_LENGTH)]) as [string, string][];\n const params = new URLSearchParams(entries);\n const item = `${params.toString()}\\n`;\n return encoder.encode(item);\n}\n\n/** Convert a response status, status text and error into an \"exception\"\n * string. */\nfunction toException(\n status: number,\n statusText: string,\n error: unknown,\n): string | undefined {\n let exception;\n if (status >= 400) {\n exception = `${status} ${statusText}`;\n if (error != null) {\n exception += ` (${String(error)})`;\n }\n }\n return exception;\n}\n\n/** Create and return a function which will dispatch messages to Google\n * Analytics.\n *\n * ### Examples\n *\n * #### Using `std/http`\n *\n * ```ts\n * import { createReporter } from \"https://deno.land/x/g_a/mod.ts\";\n * import { serve } from \"https://deno.land/std/http/server.ts\";\n * import type { ConnInfo } from \"https://deno.land/std/http/server.ts\";\n *\n * const ga = createReporter();\n *\n * function handler(req: Request, conn: ConnInfo) {\n * let err;\n * let res: Response;\n * const start = performance.now();\n * try {\n * // processing of the request...\n * res = new Response();\n * } catch (e) {\n * err = e;\n * } finally {\n * ga(req, conn, res!, start, err);\n * }\n * return res!;\n * }\n *\n * serve(handler);\n * ```\n *\n * #### Using low level APIs\n *\n * ```ts\n * import { createReporter } from \"https://deno.land/x/g_a/mod.ts\";\n *\n * const ga = createReporter();\n *\n * for await (const conn of Deno.listen({ port: 0 })) {\n * (async () => {\n * const httpConn = Deno.serveHttp(conn);\n * for await (const requestEvent of httpConn) {\n * let err;\n * const start = performance.now();\n * try {\n * // processing of the request...\n * const response = new Response();\n * await requestEvent.respondWith(response);\n * } catch (e) {\n * err = e;\n * } finally {\n * await ga(requestEvent.request, conn, response, start, err);\n * }\n * }\n * })();\n * }\n * ```\n *\n * @param options an optional set of options the impact the behavior of the\n * returned reporter.\n * @returns the reporter function used to enqueue messages to dispatch to Google\n * Analytics. */\nexport function createReporter(options: ReporterOptions = {}): Reporter {\n const {\n endpoint = GA_BATCH_ENDPOINT,\n filter = () => true,\n id = Deno.env.get(GA_TRACKING_ID),\n log = defaultLog,\n metaData = () => undefined,\n warn = true,\n } = options;\n if (!id && warn) {\n log(\n \"GA_TRACKING_ID environment variable not set. Google Analytics reporting disabled.\",\n );\n }\n const enqueue = createEnqueue(endpoint, log, warn);\n\n return async function report(\n req: Request,\n conn: Conn,\n res: Response,\n start: number,\n error?: unknown,\n ) {\n // Cannot report if no analytics ID\n if (!id) {\n return;\n }\n\n // Do not report 1XX or 3XX statuses to GA\n if (!(res.ok || res.status >= 400)) {\n return;\n }\n\n // Filter out any unwanted requests\n if (!filter(req, res)) {\n return;\n }\n\n const duration = performance.now() - start;\n\n const status = res.status;\n const statusText = res.statusText || STATUS_TEXT.get(status) || `${status}`;\n const userAgent = req.headers.get(\"user-agent\");\n // TODO(@piscisaureus): validate that the 'cf-connecting-ip' header was\n // actually set by cloudflare. See https://www.cloudflare.com/en-gb/ips/.\n const [ip] = (req.headers.get(\"x-forwarded-for\") ??\n req.headers.get(\"cf-connecting-ip\") ??\n (conn.remoteAddr as Deno.NetAddr).hostname).split(/\\s*,\\s*/);\n const { documentTitle, campaignMedium, campaignSource } =\n metaData(req, res) ??\n {};\n const exception = toException(status, statusText, error);\n const hitType = exception != null ? \"exception\" : \"pageview\";\n\n const message = {\n v: 1, // version, should always be 1\n tid: id,\n t: hitType, // event type\n cid: await toDigest(ip), // GA requires `cid` to be set.\n uip: ip,\n dl: req.url,\n dt: documentTitle,\n dr: req.headers.get(\"referer\"),\n cm: campaignMedium,\n cs: campaignSource,\n ua: userAgent,\n exd: exception,\n exf: exception != null,\n srt: duration,\n qt: uploading ? 0 : UPLOAD_DELAY,\n } as const;\n\n const payload = toPayload(message);\n if (payload.length > GA_MAX_PAYLOAD_LENGTH) {\n if (warn) {\n log(`payload exceeds maximum size: ${JSON.stringify(message)}`);\n }\n return;\n }\n enqueue(payload);\n };\n}\n\n/** Creates and returns a reporting measurement middleware for oak, which will\n * generate and send to Google Analytics measurements for each request handled\n * by an oak application.\n *\n * ### Examples\n *\n * ```ts\n * import { createReportMiddleware } from \"https://deno.land/x/g_a/mod.ts\";\n * import { Application } from \"https://deno.land/x/oak/mod.ts\";\n *\n * const ga = createReportMiddleware();\n * const app = new Application();\n *\n * app.use(ga);\n * // register additional middleware...\n *\n * app.listen({ port: 0 });\n * ```\n *\n * @param options an optional set of options which affects the behavior of the\n * returned middleware.\n * @returns middleware which should be registered early in the stack with the\n * application.\n */\nexport function createReportMiddleware(\n options: ReportMiddlewareOptions = {},\n): Middleware {\n const {\n endpoint = GA_BATCH_ENDPOINT,\n filter = () => true,\n id = Deno.env.get(GA_TRACKING_ID),\n log = defaultLog,\n metaData = () => undefined,\n warn = true,\n } = options;\n if (!id && warn) {\n log(\n \"GA_TRACKING_ID environment variable not set. Google Analytics reporting disabled.\",\n );\n }\n const enqueue = createEnqueue(endpoint, log, warn);\n\n return async function reporter(ctx, next) {\n if (!id || !filter(ctx)) {\n return next();\n }\n let error: unknown;\n const start = performance.now();\n try {\n await next();\n } catch (e) {\n error = e;\n } finally {\n // Only report 2XX and >= 4XX status to GA\n const status = ctx.response.status;\n if ((status >= 200 && status < 300) || status >= 400) {\n const duration = performance.now() - start;\n\n const statusText = STATUS_TEXT.get(status) ?? `${status}`;\n const ip = ctx.request.ip;\n const { documentTitle, campaignMedium, campaignSource } =\n metaData(ctx) ??\n {};\n const exception = toException(status, statusText, error);\n const hitType = exception != null ? \"exception\" : \"pageview\";\n\n const message = {\n v: 1, // version, should always be 1\n tid: id,\n t: hitType, // event type\n cid: await toDigest(ip), // GA requires `cid` to be set.\n uip: ip,\n dl: ctx.request.url.toString(),\n dt: documentTitle,\n dr: ctx.request.headers.get(\"referer\"),\n cm: campaignMedium,\n cs: campaignSource,\n ua: ctx.request.headers.get(\"user-agent\"),\n exd: exception,\n exf: exception != null,\n srt: duration,\n qt: uploading ? 0 : UPLOAD_DELAY,\n } as const;\n\n const payload = toPayload(message);\n if (payload.length <= GA_MAX_PAYLOAD_LENGTH) {\n enqueue(payload);\n } else if (warn) {\n log(`payload exceeds maximum size: ${JSON.stringify(message)}`);\n }\n }\n }\n };\n}\n", - "transpiled": "// Copyright 2021-2022 the Deno authors. All rights reserved. MIT license.\nimport { delay } from \"https://deno.land/std@0.120.0/async/mod.ts\";\nimport * as colors from \"https://deno.land/std@0.120.0/fmt/colors.ts\";\nimport { STATUS_TEXT } from \"https://deno.land/std@0.120.0/http/http_status.ts\";\nconst GA_TRACKING_ID = \"GA_TRACKING_ID\";\nconst GA_BATCH_ENDPOINT = \"https://www.google-analytics.com/batch\";\nconst GA_MAX_PARAM_LENGTH = 2048; // 2kb\nconst GA_MAX_PAYLOAD_LENGTH = 8092; // 8kb\nconst GA_MAX_BATCH_PAYLOAD_COUNT = 20;\nconst GA_MAX_BATCH_LENGTH = 16386; // 16kb\nconst UPLOAD_DELAY = 1000;\nconst SLOW_UPLOAD_THRESHOLD = 1000;\nconst encoder = new TextEncoder();\nconst batch = new Uint8Array(GA_MAX_BATCH_LENGTH);\nconst queue = [];\nlet uploading = false;\n/** Create a queue that dispatches queued messages to the endpoint, returning\n * the enqueue function. */ function createEnqueue(endpoint, log, warn) {\n async function upload() {\n while(queue.length){\n let count = 0;\n let length = 0;\n while(count < Math.min(queue.length, GA_MAX_BATCH_PAYLOAD_COUNT)){\n const payload = queue[count];\n if (length + payload.length > GA_MAX_BATCH_LENGTH) {\n break;\n }\n batch.set(payload, length);\n count += 1;\n length += payload.length;\n }\n const body = batch.subarray(0, length);\n try {\n const start = performance.now();\n const res = await fetch(endpoint, {\n method: \"POST\",\n body\n });\n const duration = performance.now() - start;\n if ((res.status !== 200 || duration >= SLOW_UPLOAD_THRESHOLD) && warn) {\n log(`batch uploaded ${count} items in ${duration}ms. Response: ${res.status} ${res.statusText}`);\n }\n // Google says not to retry when it reports a non-200 status code.\n queue.splice(0, count);\n } catch (err) {\n if (warn) {\n log(`batch upload failed: ${err}`);\n }\n await delay(UPLOAD_DELAY);\n }\n }\n uploading = false;\n }\n return function enqueue(payload) {\n queue.push(payload);\n if (!uploading) {\n uploading = true;\n setTimeout(upload, UPLOAD_DELAY);\n }\n };\n}\nfunction defaultLog(msg) {\n console.warn(`[ga] ${colors.yellow(\"warn\")}: ${msg}`);\n}\n/** Create a SHA-1 hex string digest of the supplied message. */ async function toDigest(msg) {\n const buffer = await crypto.subtle.digest(\"SHA-1\", encoder.encode(msg));\n return Array.from(new Uint8Array(buffer)).map((b)=>b.toString(16).padStart(2, \"0\")\n ).join(\"\");\n}\n/** Convert a Google Analytics message into a Uint8Array. */ function toPayload(message) {\n const entries = Object.entries(message).filter(([, v])=>v\n ).map(([k, v])=>[\n k,\n String(v).slice(0, GA_MAX_PARAM_LENGTH)\n ]\n );\n const params = new URLSearchParams(entries);\n const item = `${params.toString()}\\n`;\n return encoder.encode(item);\n}\n/** Convert a response status, status text and error into an \"exception\"\n * string. */ function toException(status, statusText, error) {\n let exception;\n if (status >= 400) {\n exception = `${status} ${statusText}`;\n if (error != null) {\n exception += ` (${String(error)})`;\n }\n }\n return exception;\n}\n/** Create and return a function which will dispatch messages to Google\n * Analytics.\n *\n * ### Examples\n *\n * #### Using `std/http`\n *\n * ```ts\n * import { createReporter } from \"https://deno.land/x/g_a/mod.ts\";\n * import { serve } from \"https://deno.land/std/http/server.ts\";\n * import type { ConnInfo } from \"https://deno.land/std/http/server.ts\";\n *\n * const ga = createReporter();\n *\n * function handler(req: Request, conn: ConnInfo) {\n * let err;\n * let res: Response;\n * const start = performance.now();\n * try {\n * // processing of the request...\n * res = new Response();\n * } catch (e) {\n * err = e;\n * } finally {\n * ga(req, conn, res!, start, err);\n * }\n * return res!;\n * }\n *\n * serve(handler);\n * ```\n *\n * #### Using low level APIs\n *\n * ```ts\n * import { createReporter } from \"https://deno.land/x/g_a/mod.ts\";\n *\n * const ga = createReporter();\n *\n * for await (const conn of Deno.listen({ port: 0 })) {\n * (async () => {\n * const httpConn = Deno.serveHttp(conn);\n * for await (const requestEvent of httpConn) {\n * let err;\n * const start = performance.now();\n * try {\n * // processing of the request...\n * const response = new Response();\n * await requestEvent.respondWith(response);\n * } catch (e) {\n * err = e;\n * } finally {\n * await ga(requestEvent.request, conn, response, start, err);\n * }\n * }\n * })();\n * }\n * ```\n *\n * @param options an optional set of options the impact the behavior of the\n * returned reporter.\n * @returns the reporter function used to enqueue messages to dispatch to Google\n * Analytics. */ export function createReporter(options = {\n}) {\n const { endpoint =GA_BATCH_ENDPOINT , filter =()=>true\n , id =Deno.env.get(GA_TRACKING_ID) , log =defaultLog , metaData =()=>undefined\n , warn =true , } = options;\n if (!id && warn) {\n log(\"GA_TRACKING_ID environment variable not set. Google Analytics reporting disabled.\");\n }\n const enqueue = createEnqueue(endpoint, log, warn);\n return async function report(req, conn, res, start, error) {\n // Cannot report if no analytics ID\n if (!id) {\n return;\n }\n // Do not report 1XX or 3XX statuses to GA\n if (!(res.ok || res.status >= 400)) {\n return;\n }\n // Filter out any unwanted requests\n if (!filter(req, res)) {\n return;\n }\n const duration = performance.now() - start;\n const status = res.status;\n const statusText = res.statusText || STATUS_TEXT.get(status) || `${status}`;\n const userAgent = req.headers.get(\"user-agent\");\n // TODO(@piscisaureus): validate that the 'cf-connecting-ip' header was\n // actually set by cloudflare. See https://www.cloudflare.com/en-gb/ips/.\n const [ip] = ((req.headers.get(\"x-forwarded-for\") ?? req.headers.get(\"cf-connecting-ip\")) ?? conn.remoteAddr.hostname).split(/\\s*,\\s*/);\n const { documentTitle , campaignMedium , campaignSource } = metaData(req, res) ?? {\n };\n const exception = toException(status, statusText, error);\n const hitType = exception != null ? \"exception\" : \"pageview\";\n const message = {\n v: 1,\n tid: id,\n t: hitType,\n cid: await toDigest(ip),\n uip: ip,\n dl: req.url,\n dt: documentTitle,\n dr: req.headers.get(\"referer\"),\n cm: campaignMedium,\n cs: campaignSource,\n ua: userAgent,\n exd: exception,\n exf: exception != null,\n srt: duration,\n qt: uploading ? 0 : UPLOAD_DELAY\n };\n const payload = toPayload(message);\n if (payload.length > GA_MAX_PAYLOAD_LENGTH) {\n if (warn) {\n log(`payload exceeds maximum size: ${JSON.stringify(message)}`);\n }\n return;\n }\n enqueue(payload);\n };\n}\n/** Creates and returns a reporting measurement middleware for oak, which will\n * generate and send to Google Analytics measurements for each request handled\n * by an oak application.\n *\n * ### Examples\n *\n * ```ts\n * import { createReportMiddleware } from \"https://deno.land/x/g_a/mod.ts\";\n * import { Application } from \"https://deno.land/x/oak/mod.ts\";\n *\n * const ga = createReportMiddleware();\n * const app = new Application();\n *\n * app.use(ga);\n * // register additional middleware...\n *\n * app.listen({ port: 0 });\n * ```\n *\n * @param options an optional set of options which affects the behavior of the\n * returned middleware.\n * @returns middleware which should be registered early in the stack with the\n * application.\n */ export function createReportMiddleware(options = {\n}) {\n const { endpoint =GA_BATCH_ENDPOINT , filter =()=>true\n , id =Deno.env.get(GA_TRACKING_ID) , log =defaultLog , metaData =()=>undefined\n , warn =true , } = options;\n if (!id && warn) {\n log(\"GA_TRACKING_ID environment variable not set. Google Analytics reporting disabled.\");\n }\n const enqueue = createEnqueue(endpoint, log, warn);\n return async function reporter(ctx, next) {\n if (!id || !filter(ctx)) {\n return next();\n }\n let error;\n const start = performance.now();\n try {\n await next();\n } catch (e) {\n error = e;\n } finally{\n // Only report 2XX and >= 4XX status to GA\n const status = ctx.response.status;\n if (status >= 200 && status < 300 || status >= 400) {\n const duration = performance.now() - start;\n const statusText = STATUS_TEXT.get(status) ?? `${status}`;\n const ip = ctx.request.ip;\n const { documentTitle , campaignMedium , campaignSource } = metaData(ctx) ?? {\n };\n const exception = toException(status, statusText, error);\n const hitType = exception != null ? \"exception\" : \"pageview\";\n const message = {\n v: 1,\n tid: id,\n t: hitType,\n cid: await toDigest(ip),\n uip: ip,\n dl: ctx.request.url.toString(),\n dt: documentTitle,\n dr: ctx.request.headers.get(\"referer\"),\n cm: campaignMedium,\n cs: campaignSource,\n ua: ctx.request.headers.get(\"user-agent\"),\n exd: exception,\n exf: exception != null,\n srt: duration,\n qt: uploading ? 0 : UPLOAD_DELAY\n };\n const payload = toPayload(message);\n if (payload.length <= GA_MAX_PAYLOAD_LENGTH) {\n enqueue(payload);\n } else if (warn) {\n log(`payload exceeds maximum size: ${JSON.stringify(message)}`);\n }\n }\n }\n };\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L2dfYUAwLjEuMi9tb2QudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEVBQTBFLEFBQTFFLHdFQUEwRTtBQUUxRSxNQUFNLEdBQUcsS0FBSyxRQUFRLENBQTRDO0FBQ2xFLE1BQU0sTUFBTSxNQUFNLE1BQU0sQ0FBNkM7QUFDckUsTUFBTSxHQUFHLFdBQVcsUUFBUSxDQUFtRDtBQUkvRSxLQUFLLENBQUMsY0FBYyxHQUFHLENBQWdCO0FBQ3ZDLEtBQUssQ0FBQyxpQkFBaUIsR0FBRyxDQUF3QztBQUNsRSxLQUFLLENBQUMsbUJBQW1CLEdBQUcsSUFBSyxDQUFFLENBQU0sQUFBTixFQUFNLEFBQU4sSUFBTTtBQUN6QyxLQUFLLENBQUMscUJBQXFCLEdBQUcsSUFBSyxDQUFFLENBQU0sQUFBTixFQUFNLEFBQU4sSUFBTTtBQUMzQyxLQUFLLENBQUMsMEJBQTBCLEdBQUcsRUFBRTtBQUNyQyxLQUFLLENBQUMsbUJBQW1CLEdBQUcsS0FBTSxDQUFFLENBQU8sQUFBUCxFQUFPLEFBQVAsS0FBTztBQUMzQyxLQUFLLENBQUMsWUFBWSxHQUFHLElBQUs7QUFDMUIsS0FBSyxDQUFDLHFCQUFxQixHQUFHLElBQUs7QUEwSW5DLEtBQUssQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDLFdBQVc7QUFDL0IsS0FBSyxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLG1CQUFtQjtBQUNoRCxLQUFLLENBQUMsS0FBSyxHQUFpQixDQUFDLENBQUM7QUFDOUIsR0FBRyxDQUFDLFNBQVMsR0FBRyxLQUFLO0FBRXJCLEVBQzJCLEFBRDNCO3lCQUMyQixBQUQzQixFQUMyQixVQUNsQixhQUFhLENBQ3BCLFFBQWdCLEVBQ2hCLEdBQTBCLEVBQzFCLElBQWEsRUFDYixDQUFDO21CQUNjLE1BQU0sR0FBRyxDQUFDO2NBQ2hCLEtBQUssQ0FBQyxNQUFNLENBQUUsQ0FBQztZQUNwQixHQUFHLENBQUMsS0FBSyxHQUFHLENBQUM7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", - "content_type": "application/typescript; charset=utf-8", - "deps": [ - "https://deno.land/std@0.120.0/async/mod.ts", - "https://deno.land/std@0.120.0/fmt/colors.ts", - "https://deno.land/std@0.120.0/http/http_status.ts" - ] - } - }, - "https://deno.land/std@0.120.0/http/http_status.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n/**\n * Enum of HTTP status codes.\n *\n * ```ts\n * import {\n * Status,\n * STATUS_TEXT,\n * } from \"https://deno.land/std@$STD_VERSION/http/http_status.ts\";\n *\n * console.log(Status.NotFound); //=> 404\n * console.log(STATUS_TEXT.get(Status.NotFound)); //=> \"Not Found\"\n * ```\n */\nexport enum Status {\n /** RFC 7231, 6.2.1 */\n Continue = 100,\n /** RFC 7231, 6.2.2 */\n SwitchingProtocols = 101,\n /** RFC 2518, 10.1 */\n Processing = 102,\n /** RFC 8297 **/\n EarlyHints = 103,\n /** RFC 7231, 6.3.1 */\n OK = 200,\n /** RFC 7231, 6.3.2 */\n Created = 201,\n /** RFC 7231, 6.3.3 */\n Accepted = 202,\n /** RFC 7231, 6.3.4 */\n NonAuthoritativeInfo = 203,\n /** RFC 7231, 6.3.5 */\n NoContent = 204,\n /** RFC 7231, 6.3.6 */\n ResetContent = 205,\n /** RFC 7233, 4.1 */\n PartialContent = 206,\n /** RFC 4918, 11.1 */\n MultiStatus = 207,\n /** RFC 5842, 7.1 */\n AlreadyReported = 208,\n /** RFC 3229, 10.4.1 */\n IMUsed = 226,\n\n /** RFC 7231, 6.4.1 */\n MultipleChoices = 300,\n /** RFC 7231, 6.4.2 */\n MovedPermanently = 301,\n /** RFC 7231, 6.4.3 */\n Found = 302,\n /** RFC 7231, 6.4.4 */\n SeeOther = 303,\n /** RFC 7232, 4.1 */\n NotModified = 304,\n /** RFC 7231, 6.4.5 */\n UseProxy = 305,\n /** RFC 7231, 6.4.7 */\n TemporaryRedirect = 307,\n /** RFC 7538, 3 */\n PermanentRedirect = 308,\n\n /** RFC 7231, 6.5.1 */\n BadRequest = 400,\n /** RFC 7235, 3.1 */\n Unauthorized = 401,\n /** RFC 7231, 6.5.2 */\n PaymentRequired = 402,\n /** RFC 7231, 6.5.3 */\n Forbidden = 403,\n /** RFC 7231, 6.5.4 */\n NotFound = 404,\n /** RFC 7231, 6.5.5 */\n MethodNotAllowed = 405,\n /** RFC 7231, 6.5.6 */\n NotAcceptable = 406,\n /** RFC 7235, 3.2 */\n ProxyAuthRequired = 407,\n /** RFC 7231, 6.5.7 */\n RequestTimeout = 408,\n /** RFC 7231, 6.5.8 */\n Conflict = 409,\n /** RFC 7231, 6.5.9 */\n Gone = 410,\n /** RFC 7231, 6.5.10 */\n LengthRequired = 411,\n /** RFC 7232, 4.2 */\n PreconditionFailed = 412,\n /** RFC 7231, 6.5.11 */\n RequestEntityTooLarge = 413,\n /** RFC 7231, 6.5.12 */\n RequestURITooLong = 414,\n /** RFC 7231, 6.5.13 */\n UnsupportedMediaType = 415,\n /** RFC 7233, 4.4 */\n RequestedRangeNotSatisfiable = 416,\n /** RFC 7231, 6.5.14 */\n ExpectationFailed = 417,\n /** RFC 7168, 2.3.3 */\n Teapot = 418,\n /** RFC 7540, 9.1.2 */\n MisdirectedRequest = 421,\n /** RFC 4918, 11.2 */\n UnprocessableEntity = 422,\n /** RFC 4918, 11.3 */\n Locked = 423,\n /** RFC 4918, 11.4 */\n FailedDependency = 424,\n /** RFC 8470, 5.2 */\n TooEarly = 425,\n /** RFC 7231, 6.5.15 */\n UpgradeRequired = 426,\n /** RFC 6585, 3 */\n PreconditionRequired = 428,\n /** RFC 6585, 4 */\n TooManyRequests = 429,\n /** RFC 6585, 5 */\n RequestHeaderFieldsTooLarge = 431,\n /** RFC 7725, 3 */\n UnavailableForLegalReasons = 451,\n\n /** RFC 7231, 6.6.1 */\n InternalServerError = 500,\n /** RFC 7231, 6.6.2 */\n NotImplemented = 501,\n /** RFC 7231, 6.6.3 */\n BadGateway = 502,\n /** RFC 7231, 6.6.4 */\n ServiceUnavailable = 503,\n /** RFC 7231, 6.6.5 */\n GatewayTimeout = 504,\n /** RFC 7231, 6.6.6 */\n HTTPVersionNotSupported = 505,\n /** RFC 2295, 8.1 */\n VariantAlsoNegotiates = 506,\n /** RFC 4918, 11.5 */\n InsufficientStorage = 507,\n /** RFC 5842, 7.2 */\n LoopDetected = 508,\n /** RFC 2774, 7 */\n NotExtended = 510,\n /** RFC 6585, 6 */\n NetworkAuthenticationRequired = 511,\n}\n\n/**\n * Map from status code to status text.\n *\n * ```ts\n * import {\n * Status,\n * STATUS_TEXT,\n * } from \"https://deno.land/std@$STD_VERSION/http/http_status.ts\";\n *\n * console.log(Status.NotFound); //=> 404\n * console.log(STATUS_TEXT.get(Status.NotFound)); //=> \"Not Found\"\n * ```\n */\nexport const STATUS_TEXT = new Map([\n [Status.Continue, \"Continue\"],\n [Status.SwitchingProtocols, \"Switching Protocols\"],\n [Status.Processing, \"Processing\"],\n [Status.EarlyHints, \"Early Hints\"],\n [Status.OK, \"OK\"],\n [Status.Created, \"Created\"],\n [Status.Accepted, \"Accepted\"],\n [Status.NonAuthoritativeInfo, \"Non-Authoritative Information\"],\n [Status.NoContent, \"No Content\"],\n [Status.ResetContent, \"Reset Content\"],\n [Status.PartialContent, \"Partial Content\"],\n [Status.MultiStatus, \"Multi-Status\"],\n [Status.AlreadyReported, \"Already Reported\"],\n [Status.IMUsed, \"IM Used\"],\n [Status.MultipleChoices, \"Multiple Choices\"],\n [Status.MovedPermanently, \"Moved Permanently\"],\n [Status.Found, \"Found\"],\n [Status.SeeOther, \"See Other\"],\n [Status.NotModified, \"Not Modified\"],\n [Status.UseProxy, \"Use Proxy\"],\n [Status.TemporaryRedirect, \"Temporary Redirect\"],\n [Status.PermanentRedirect, \"Permanent Redirect\"],\n [Status.BadRequest, \"Bad Request\"],\n [Status.Unauthorized, \"Unauthorized\"],\n [Status.PaymentRequired, \"Payment Required\"],\n [Status.Forbidden, \"Forbidden\"],\n [Status.NotFound, \"Not Found\"],\n [Status.MethodNotAllowed, \"Method Not Allowed\"],\n [Status.NotAcceptable, \"Not Acceptable\"],\n [Status.ProxyAuthRequired, \"Proxy Authentication Required\"],\n [Status.RequestTimeout, \"Request Timeout\"],\n [Status.Conflict, \"Conflict\"],\n [Status.Gone, \"Gone\"],\n [Status.LengthRequired, \"Length Required\"],\n [Status.PreconditionFailed, \"Precondition Failed\"],\n [Status.RequestEntityTooLarge, \"Request Entity Too Large\"],\n [Status.RequestURITooLong, \"Request URI Too Long\"],\n [Status.UnsupportedMediaType, \"Unsupported Media Type\"],\n [Status.RequestedRangeNotSatisfiable, \"Requested Range Not Satisfiable\"],\n [Status.ExpectationFailed, \"Expectation Failed\"],\n [Status.Teapot, \"I'm a teapot\"],\n [Status.MisdirectedRequest, \"Misdirected Request\"],\n [Status.UnprocessableEntity, \"Unprocessable Entity\"],\n [Status.Locked, \"Locked\"],\n [Status.FailedDependency, \"Failed Dependency\"],\n [Status.TooEarly, \"Too Early\"],\n [Status.UpgradeRequired, \"Upgrade Required\"],\n [Status.PreconditionRequired, \"Precondition Required\"],\n [Status.TooManyRequests, \"Too Many Requests\"],\n [Status.RequestHeaderFieldsTooLarge, \"Request Header Fields Too Large\"],\n [Status.UnavailableForLegalReasons, \"Unavailable For Legal Reasons\"],\n [Status.InternalServerError, \"Internal Server Error\"],\n [Status.NotImplemented, \"Not Implemented\"],\n [Status.BadGateway, \"Bad Gateway\"],\n [Status.ServiceUnavailable, \"Service Unavailable\"],\n [Status.GatewayTimeout, \"Gateway Timeout\"],\n [Status.HTTPVersionNotSupported, \"HTTP Version Not Supported\"],\n [Status.VariantAlsoNegotiates, \"Variant Also Negotiates\"],\n [Status.InsufficientStorage, \"Insufficient Storage\"],\n [Status.LoopDetected, \"Loop Detected\"],\n [Status.NotExtended, \"Not Extended\"],\n [Status.NetworkAuthenticationRequired, \"Network Authentication Required\"],\n]);\n", - "transpiled": "export var Status;\n(function(Status) {\n Status[Status[/** RFC 7231, 6.2.1 */ \"Continue\"] = 100] = \"Continue\";\n Status[Status[/** RFC 7231, 6.2.2 */ \"SwitchingProtocols\"] = 101] = \"SwitchingProtocols\";\n Status[Status[/** RFC 2518, 10.1 */ \"Processing\"] = 102] = \"Processing\";\n Status[Status[/** RFC 8297 **/ \"EarlyHints\"] = 103] = \"EarlyHints\";\n Status[Status[/** RFC 7231, 6.3.1 */ \"OK\"] = 200] = \"OK\";\n Status[Status[/** RFC 7231, 6.3.2 */ \"Created\"] = 201] = \"Created\";\n Status[Status[/** RFC 7231, 6.3.3 */ \"Accepted\"] = 202] = \"Accepted\";\n Status[Status[/** RFC 7231, 6.3.4 */ \"NonAuthoritativeInfo\"] = 203] = \"NonAuthoritativeInfo\";\n Status[Status[/** RFC 7231, 6.3.5 */ \"NoContent\"] = 204] = \"NoContent\";\n Status[Status[/** RFC 7231, 6.3.6 */ \"ResetContent\"] = 205] = \"ResetContent\";\n Status[Status[/** RFC 7233, 4.1 */ \"PartialContent\"] = 206] = \"PartialContent\";\n Status[Status[/** RFC 4918, 11.1 */ \"MultiStatus\"] = 207] = \"MultiStatus\";\n Status[Status[/** RFC 5842, 7.1 */ \"AlreadyReported\"] = 208] = \"AlreadyReported\";\n Status[Status[/** RFC 3229, 10.4.1 */ \"IMUsed\"] = 226] = \"IMUsed\";\n Status[Status[/** RFC 7231, 6.4.1 */ \"MultipleChoices\"] = 300] = \"MultipleChoices\";\n Status[Status[/** RFC 7231, 6.4.2 */ \"MovedPermanently\"] = 301] = \"MovedPermanently\";\n Status[Status[/** RFC 7231, 6.4.3 */ \"Found\"] = 302] = \"Found\";\n Status[Status[/** RFC 7231, 6.4.4 */ \"SeeOther\"] = 303] = \"SeeOther\";\n Status[Status[/** RFC 7232, 4.1 */ \"NotModified\"] = 304] = \"NotModified\";\n Status[Status[/** RFC 7231, 6.4.5 */ \"UseProxy\"] = 305] = \"UseProxy\";\n Status[Status[/** RFC 7231, 6.4.7 */ \"TemporaryRedirect\"] = 307] = \"TemporaryRedirect\";\n Status[Status[/** RFC 7538, 3 */ \"PermanentRedirect\"] = 308] = \"PermanentRedirect\";\n Status[Status[/** RFC 7231, 6.5.1 */ \"BadRequest\"] = 400] = \"BadRequest\";\n Status[Status[/** RFC 7235, 3.1 */ \"Unauthorized\"] = 401] = \"Unauthorized\";\n Status[Status[/** RFC 7231, 6.5.2 */ \"PaymentRequired\"] = 402] = \"PaymentRequired\";\n Status[Status[/** RFC 7231, 6.5.3 */ \"Forbidden\"] = 403] = \"Forbidden\";\n Status[Status[/** RFC 7231, 6.5.4 */ \"NotFound\"] = 404] = \"NotFound\";\n Status[Status[/** RFC 7231, 6.5.5 */ \"MethodNotAllowed\"] = 405] = \"MethodNotAllowed\";\n Status[Status[/** RFC 7231, 6.5.6 */ \"NotAcceptable\"] = 406] = \"NotAcceptable\";\n Status[Status[/** RFC 7235, 3.2 */ \"ProxyAuthRequired\"] = 407] = \"ProxyAuthRequired\";\n Status[Status[/** RFC 7231, 6.5.7 */ \"RequestTimeout\"] = 408] = \"RequestTimeout\";\n Status[Status[/** RFC 7231, 6.5.8 */ \"Conflict\"] = 409] = \"Conflict\";\n Status[Status[/** RFC 7231, 6.5.9 */ \"Gone\"] = 410] = \"Gone\";\n Status[Status[/** RFC 7231, 6.5.10 */ \"LengthRequired\"] = 411] = \"LengthRequired\";\n Status[Status[/** RFC 7232, 4.2 */ \"PreconditionFailed\"] = 412] = \"PreconditionFailed\";\n Status[Status[/** RFC 7231, 6.5.11 */ \"RequestEntityTooLarge\"] = 413] = \"RequestEntityTooLarge\";\n Status[Status[/** RFC 7231, 6.5.12 */ \"RequestURITooLong\"] = 414] = \"RequestURITooLong\";\n Status[Status[/** RFC 7231, 6.5.13 */ \"UnsupportedMediaType\"] = 415] = \"UnsupportedMediaType\";\n Status[Status[/** RFC 7233, 4.4 */ \"RequestedRangeNotSatisfiable\"] = 416] = \"RequestedRangeNotSatisfiable\";\n Status[Status[/** RFC 7231, 6.5.14 */ \"ExpectationFailed\"] = 417] = \"ExpectationFailed\";\n Status[Status[/** RFC 7168, 2.3.3 */ \"Teapot\"] = 418] = \"Teapot\";\n Status[Status[/** RFC 7540, 9.1.2 */ \"MisdirectedRequest\"] = 421] = \"MisdirectedRequest\";\n Status[Status[/** RFC 4918, 11.2 */ \"UnprocessableEntity\"] = 422] = \"UnprocessableEntity\";\n Status[Status[/** RFC 4918, 11.3 */ \"Locked\"] = 423] = \"Locked\";\n Status[Status[/** RFC 4918, 11.4 */ \"FailedDependency\"] = 424] = \"FailedDependency\";\n Status[Status[/** RFC 8470, 5.2 */ \"TooEarly\"] = 425] = \"TooEarly\";\n Status[Status[/** RFC 7231, 6.5.15 */ \"UpgradeRequired\"] = 426] = \"UpgradeRequired\";\n Status[Status[/** RFC 6585, 3 */ \"PreconditionRequired\"] = 428] = \"PreconditionRequired\";\n Status[Status[/** RFC 6585, 4 */ \"TooManyRequests\"] = 429] = \"TooManyRequests\";\n Status[Status[/** RFC 6585, 5 */ \"RequestHeaderFieldsTooLarge\"] = 431] = \"RequestHeaderFieldsTooLarge\";\n Status[Status[/** RFC 7725, 3 */ \"UnavailableForLegalReasons\"] = 451] = \"UnavailableForLegalReasons\";\n Status[Status[/** RFC 7231, 6.6.1 */ \"InternalServerError\"] = 500] = \"InternalServerError\";\n Status[Status[/** RFC 7231, 6.6.2 */ \"NotImplemented\"] = 501] = \"NotImplemented\";\n Status[Status[/** RFC 7231, 6.6.3 */ \"BadGateway\"] = 502] = \"BadGateway\";\n Status[Status[/** RFC 7231, 6.6.4 */ \"ServiceUnavailable\"] = 503] = \"ServiceUnavailable\";\n Status[Status[/** RFC 7231, 6.6.5 */ \"GatewayTimeout\"] = 504] = \"GatewayTimeout\";\n Status[Status[/** RFC 7231, 6.6.6 */ \"HTTPVersionNotSupported\"] = 505] = \"HTTPVersionNotSupported\";\n Status[Status[/** RFC 2295, 8.1 */ \"VariantAlsoNegotiates\"] = 506] = \"VariantAlsoNegotiates\";\n Status[Status[/** RFC 4918, 11.5 */ \"InsufficientStorage\"] = 507] = \"InsufficientStorage\";\n Status[Status[/** RFC 5842, 7.2 */ \"LoopDetected\"] = 508] = \"LoopDetected\";\n Status[Status[/** RFC 2774, 7 */ \"NotExtended\"] = 510] = \"NotExtended\";\n Status[Status[/** RFC 6585, 6 */ \"NetworkAuthenticationRequired\"] = 511] = \"NetworkAuthenticationRequired\";\n})(Status || (Status = {\n}));\n/**\n * Map from status code to status text.\n *\n * ```ts\n * import {\n * Status,\n * STATUS_TEXT,\n * } from \"https://deno.land/std@$STD_VERSION/http/http_status.ts\";\n *\n * console.log(Status.NotFound); //=> 404\n * console.log(STATUS_TEXT.get(Status.NotFound)); //=> \"Not Found\"\n * ```\n */ export const STATUS_TEXT = new Map([\n [\n Status.Continue,\n \"Continue\"\n ],\n [\n Status.SwitchingProtocols,\n \"Switching Protocols\"\n ],\n [\n Status.Processing,\n \"Processing\"\n ],\n [\n Status.EarlyHints,\n \"Early Hints\"\n ],\n [\n Status.OK,\n \"OK\"\n ],\n [\n Status.Created,\n \"Created\"\n ],\n [\n Status.Accepted,\n \"Accepted\"\n ],\n [\n Status.NonAuthoritativeInfo,\n \"Non-Authoritative Information\"\n ],\n [\n Status.NoContent,\n \"No Content\"\n ],\n [\n Status.ResetContent,\n \"Reset Content\"\n ],\n [\n Status.PartialContent,\n \"Partial Content\"\n ],\n [\n Status.MultiStatus,\n \"Multi-Status\"\n ],\n [\n Status.AlreadyReported,\n \"Already Reported\"\n ],\n [\n Status.IMUsed,\n \"IM Used\"\n ],\n [\n Status.MultipleChoices,\n \"Multiple Choices\"\n ],\n [\n Status.MovedPermanently,\n \"Moved Permanently\"\n ],\n [\n Status.Found,\n \"Found\"\n ],\n [\n Status.SeeOther,\n \"See Other\"\n ],\n [\n Status.NotModified,\n \"Not Modified\"\n ],\n [\n Status.UseProxy,\n \"Use Proxy\"\n ],\n [\n Status.TemporaryRedirect,\n \"Temporary Redirect\"\n ],\n [\n Status.PermanentRedirect,\n \"Permanent Redirect\"\n ],\n [\n Status.BadRequest,\n \"Bad Request\"\n ],\n [\n Status.Unauthorized,\n \"Unauthorized\"\n ],\n [\n Status.PaymentRequired,\n \"Payment Required\"\n ],\n [\n Status.Forbidden,\n \"Forbidden\"\n ],\n [\n Status.NotFound,\n \"Not Found\"\n ],\n [\n Status.MethodNotAllowed,\n \"Method Not Allowed\"\n ],\n [\n Status.NotAcceptable,\n \"Not Acceptable\"\n ],\n [\n Status.ProxyAuthRequired,\n \"Proxy Authentication Required\"\n ],\n [\n Status.RequestTimeout,\n \"Request Timeout\"\n ],\n [\n Status.Conflict,\n \"Conflict\"\n ],\n [\n Status.Gone,\n \"Gone\"\n ],\n [\n Status.LengthRequired,\n \"Length Required\"\n ],\n [\n Status.PreconditionFailed,\n \"Precondition Failed\"\n ],\n [\n Status.RequestEntityTooLarge,\n \"Request Entity Too Large\"\n ],\n [\n Status.RequestURITooLong,\n \"Request URI Too Long\"\n ],\n [\n Status.UnsupportedMediaType,\n \"Unsupported Media Type\"\n ],\n [\n Status.RequestedRangeNotSatisfiable,\n \"Requested Range Not Satisfiable\"\n ],\n [\n Status.ExpectationFailed,\n \"Expectation Failed\"\n ],\n [\n Status.Teapot,\n \"I'm a teapot\"\n ],\n [\n Status.MisdirectedRequest,\n \"Misdirected Request\"\n ],\n [\n Status.UnprocessableEntity,\n \"Unprocessable Entity\"\n ],\n [\n Status.Locked,\n \"Locked\"\n ],\n [\n Status.FailedDependency,\n \"Failed Dependency\"\n ],\n [\n Status.TooEarly,\n \"Too Early\"\n ],\n [\n Status.UpgradeRequired,\n \"Upgrade Required\"\n ],\n [\n Status.PreconditionRequired,\n \"Precondition Required\"\n ],\n [\n Status.TooManyRequests,\n \"Too Many Requests\"\n ],\n [\n Status.RequestHeaderFieldsTooLarge,\n \"Request Header Fields Too Large\"\n ],\n [\n Status.UnavailableForLegalReasons,\n \"Unavailable For Legal Reasons\"\n ],\n [\n Status.InternalServerError,\n \"Internal Server Error\"\n ],\n [\n Status.NotImplemented,\n \"Not Implemented\"\n ],\n [\n Status.BadGateway,\n \"Bad Gateway\"\n ],\n [\n Status.ServiceUnavailable,\n \"Service Unavailable\"\n ],\n [\n Status.GatewayTimeout,\n \"Gateway Timeout\"\n ],\n [\n Status.HTTPVersionNotSupported,\n \"HTTP Version Not Supported\"\n ],\n [\n Status.VariantAlsoNegotiates,\n \"Variant Also Negotiates\"\n ],\n [\n Status.InsufficientStorage,\n \"Insufficient Storage\"\n ],\n [\n Status.LoopDetected,\n \"Loop Detected\"\n ],\n [\n Status.NotExtended,\n \"Not Extended\"\n ],\n [\n Status.NetworkAuthenticationRequired,\n \"Network Authentication Required\"\n ], \n]);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9odHRwL2h0dHBfc3RhdHVzLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFlTyxNQUFNO1VBQUQsTUFBTTtJQUFOLE1BQU0sQ0FBTixNQUFNLENBQ2hCLEVBQXNCLEFBQXRCLGtCQUFzQixBQUF0QixFQUFzQixDQUN0QixDQUFRLGFBQUcsR0FBRyxJQUFkLENBQVE7SUFGRSxNQUFNLENBQU4sTUFBTSxDQUdoQixFQUFzQixBQUF0QixrQkFBc0IsQUFBdEIsRUFBc0IsQ0FDdEIsQ0FBa0IsdUJBQUcsR0FBRyxJQUF4QixDQUFrQjtJQUpSLE1BQU0sQ0FBTixNQUFNLENBS2hCLEVBQXFCLEFBQXJCLGlCQUFxQixBQUFyQixFQUFxQixDQUNyQixDQUFVLGVBQUcsR0FBRyxJQUFoQixDQUFVO0lBTkEsTUFBTSxDQUFOLE1BQU0sQ0FPaEIsRUFBZ0IsQUFBaEIsWUFBZ0IsQUFBaEIsRUFBZ0IsQ0FDaEIsQ0FBVSxlQUFHLEdBQUcsSUFBaEIsQ0FBVTtJQVJBLE1BQU0sQ0FBTixNQUFNLENBU2hCLEVBQXNCLEFBQXRCLGtCQUFzQixBQUF0QixFQUFzQixDQUN0QixDQUFFLE9BQUcsR0FBRyxJQUFSLENBQUU7SUFWUSxNQUFNLENBQU4sTUFBTSxDQVdoQixFQUFzQixBQUF0QixrQkFBc0IsQUFBdEIsRUFBc0IsQ0FDdEIsQ0FBTyxZQUFHLEdBQUcsSUFBYixDQUFPO0lBWkcsTUFBTSxDQUFOLE1BQU0sQ0FhaEIsRUFBc0IsQUFBdEIsa0JBQXNCLEFBQXRCLEVBQXNCLENBQ3RCLENBQVEsYUFBRyxHQUFHLElBQWQsQ0FBUTtJQWRFLE1BQU0sQ0FBTixNQUFNLENBZWhCLEVBQXNCLEFBQXRCLGtCQUFzQixBQUF0QixFQUFzQixDQUN0QixDQUFvQix5QkFBRyxHQUFHLElBQTFCLENBQW9CO0lBaEJWLE1BQU0sQ0FBTixNQUFNLENBaUJoQixFQUFzQixBQUF0QixrQkFBc0IsQUFBdEIsRUFBc0IsQ0FDdEIs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", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/x/path_to_regexp@v6.2.0/index.ts": { - "Source": { - "source": "/**\n * Tokenizer results.\n */\ninterface LexToken {\n type:\n | \"OPEN\"\n | \"CLOSE\"\n | \"PATTERN\"\n | \"NAME\"\n | \"CHAR\"\n | \"ESCAPED_CHAR\"\n | \"MODIFIER\"\n | \"END\";\n index: number;\n value: string;\n}\n\n/**\n * Tokenize input string.\n */\nfunction lexer(str: string): LexToken[] {\n const tokens: LexToken[] = [];\n let i = 0;\n\n while (i < str.length) {\n const char = str[i];\n\n if (char === \"*\" || char === \"+\" || char === \"?\") {\n tokens.push({ type: \"MODIFIER\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \"\\\\\") {\n tokens.push({ type: \"ESCAPED_CHAR\", index: i++, value: str[i++] });\n continue;\n }\n\n if (char === \"{\") {\n tokens.push({ type: \"OPEN\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \"}\") {\n tokens.push({ type: \"CLOSE\", index: i, value: str[i++] });\n continue;\n }\n\n if (char === \":\") {\n let name = \"\";\n let j = i + 1;\n\n while (j < str.length) {\n const code = str.charCodeAt(j);\n\n if (\n // `0-9`\n (code >= 48 && code <= 57) ||\n // `A-Z`\n (code >= 65 && code <= 90) ||\n // `a-z`\n (code >= 97 && code <= 122) ||\n // `_`\n code === 95\n ) {\n name += str[j++];\n continue;\n }\n\n break;\n }\n\n if (!name) throw new TypeError(`Missing parameter name at ${i}`);\n\n tokens.push({ type: \"NAME\", index: i, value: name });\n i = j;\n continue;\n }\n\n if (char === \"(\") {\n let count = 1;\n let pattern = \"\";\n let j = i + 1;\n\n if (str[j] === \"?\") {\n throw new TypeError(`Pattern cannot start with \"?\" at ${j}`);\n }\n\n while (j < str.length) {\n if (str[j] === \"\\\\\") {\n pattern += str[j++] + str[j++];\n continue;\n }\n\n if (str[j] === \")\") {\n count--;\n if (count === 0) {\n j++;\n break;\n }\n } else if (str[j] === \"(\") {\n count++;\n if (str[j + 1] !== \"?\") {\n throw new TypeError(`Capturing groups are not allowed at ${j}`);\n }\n }\n\n pattern += str[j++];\n }\n\n if (count) throw new TypeError(`Unbalanced pattern at ${i}`);\n if (!pattern) throw new TypeError(`Missing pattern at ${i}`);\n\n tokens.push({ type: \"PATTERN\", index: i, value: pattern });\n i = j;\n continue;\n }\n\n tokens.push({ type: \"CHAR\", index: i, value: str[i++] });\n }\n\n tokens.push({ type: \"END\", index: i, value: \"\" });\n\n return tokens;\n}\n\nexport interface ParseOptions {\n /**\n * Set the default delimiter for repeat parameters. (default: `'/'`)\n */\n delimiter?: string;\n /**\n * List of characters to automatically consider prefixes when parsing.\n */\n prefixes?: string;\n}\n\n/**\n * Parse a string for the raw tokens.\n */\nexport function parse(str: string, options: ParseOptions = {}): Token[] {\n const tokens = lexer(str);\n const { prefixes = \"./\" } = options;\n const defaultPattern = `[^${escapeString(options.delimiter || \"/#?\")}]+?`;\n const result: Token[] = [];\n let key = 0;\n let i = 0;\n let path = \"\";\n\n const tryConsume = (type: LexToken[\"type\"]): string | undefined => {\n if (i < tokens.length && tokens[i].type === type) return tokens[i++].value;\n };\n\n const mustConsume = (type: LexToken[\"type\"]): string => {\n const value = tryConsume(type);\n if (value !== undefined) return value;\n const { type: nextType, index } = tokens[i];\n throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}`);\n };\n\n const consumeText = (): string => {\n let result = \"\";\n let value: string | undefined;\n // tslint:disable-next-line\n while ((value = tryConsume(\"CHAR\") || tryConsume(\"ESCAPED_CHAR\"))) {\n result += value;\n }\n return result;\n };\n\n while (i < tokens.length) {\n const char = tryConsume(\"CHAR\");\n const name = tryConsume(\"NAME\");\n const pattern = tryConsume(\"PATTERN\");\n\n if (name || pattern) {\n let prefix = char || \"\";\n\n if (prefixes.indexOf(prefix) === -1) {\n path += prefix;\n prefix = \"\";\n }\n\n if (path) {\n result.push(path);\n path = \"\";\n }\n\n result.push({\n name: name || key++,\n prefix,\n suffix: \"\",\n pattern: pattern || defaultPattern,\n modifier: tryConsume(\"MODIFIER\") || \"\"\n });\n continue;\n }\n\n const value = char || tryConsume(\"ESCAPED_CHAR\");\n if (value) {\n path += value;\n continue;\n }\n\n if (path) {\n result.push(path);\n path = \"\";\n }\n\n const open = tryConsume(\"OPEN\");\n if (open) {\n const prefix = consumeText();\n const name = tryConsume(\"NAME\") || \"\";\n const pattern = tryConsume(\"PATTERN\") || \"\";\n const suffix = consumeText();\n\n mustConsume(\"CLOSE\");\n\n result.push({\n name: name || (pattern ? key++ : \"\"),\n pattern: name && !pattern ? defaultPattern : pattern,\n prefix,\n suffix,\n modifier: tryConsume(\"MODIFIER\") || \"\"\n });\n continue;\n }\n\n mustConsume(\"END\");\n }\n\n return result;\n}\n\nexport interface TokensToFunctionOptions {\n /**\n * When `true` the regexp will be case sensitive. (default: `false`)\n */\n sensitive?: boolean;\n /**\n * Function for encoding input strings for output.\n */\n encode?: (value: string, token: Key) => string;\n /**\n * When `false` the function can produce an invalid (unmatched) path. (default: `true`)\n */\n validate?: boolean;\n}\n\n/**\n * Compile a string to a template function for the path.\n */\nexport function compile

(\n str: string,\n options?: ParseOptions & TokensToFunctionOptions\n) {\n return tokensToFunction

(parse(str, options), options);\n}\n\nexport type PathFunction

= (data?: P) => string;\n\n/**\n * Expose a method for transforming tokens into the path function.\n */\nexport function tokensToFunction

(\n tokens: Token[],\n options: TokensToFunctionOptions = {}\n): PathFunction

{\n const reFlags = flags(options);\n const { encode = (x: string) => x, validate = true } = options;\n\n // Compile all the tokens into regexps.\n const matches = tokens.map(token => {\n if (typeof token === \"object\") {\n return new RegExp(`^(?:${token.pattern})$`, reFlags);\n }\n });\n\n return (data: Record | null | undefined) => {\n let path = \"\";\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n\n if (typeof token === \"string\") {\n path += token;\n continue;\n }\n\n const value = data ? data[token.name] : undefined;\n const optional = token.modifier === \"?\" || token.modifier === \"*\";\n const repeat = token.modifier === \"*\" || token.modifier === \"+\";\n\n if (Array.isArray(value)) {\n if (!repeat) {\n throw new TypeError(\n `Expected \"${token.name}\" to not repeat, but got an array`\n );\n }\n\n if (value.length === 0) {\n if (optional) continue;\n\n throw new TypeError(`Expected \"${token.name}\" to not be empty`);\n }\n\n for (let j = 0; j < value.length; j++) {\n const segment = encode(value[j], token);\n\n if (validate && !(matches[i] as RegExp).test(segment)) {\n throw new TypeError(\n `Expected all \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`\n );\n }\n\n path += token.prefix + segment + token.suffix;\n }\n\n continue;\n }\n\n if (typeof value === \"string\" || typeof value === \"number\") {\n const segment = encode(String(value), token);\n\n if (validate && !(matches[i] as RegExp).test(segment)) {\n throw new TypeError(\n `Expected \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`\n );\n }\n\n path += token.prefix + segment + token.suffix;\n continue;\n }\n\n if (optional) continue;\n\n const typeOfMessage = repeat ? \"an array\" : \"a string\";\n throw new TypeError(`Expected \"${token.name}\" to be ${typeOfMessage}`);\n }\n\n return path;\n };\n}\n\nexport interface RegexpToFunctionOptions {\n /**\n * Function for decoding strings for params.\n */\n decode?: (value: string, token: Key) => string;\n}\n\n/**\n * A match result contains data about the path match.\n */\nexport interface MatchResult

{\n path: string;\n index: number;\n params: P;\n}\n\n/**\n * A match is either `false` (no match) or a match result.\n */\nexport type Match

= false | MatchResult

;\n\n/**\n * The match function takes a string and returns whether it matched the path.\n */\nexport type MatchFunction

= (\n path: string\n) => Match

;\n\n/**\n * Create path match function from `path-to-regexp` spec.\n */\nexport function match

(\n str: Path,\n options?: ParseOptions & TokensToRegexpOptions & RegexpToFunctionOptions\n) {\n const keys: Key[] = [];\n const re = pathToRegexp(str, keys, options);\n return regexpToFunction

(re, keys, options);\n}\n\n/**\n * Create a path match function from `path-to-regexp` output.\n */\nexport function regexpToFunction

(\n re: RegExp,\n keys: Key[],\n options: RegexpToFunctionOptions = {}\n): MatchFunction

{\n const { decode = (x: string) => x } = options;\n\n return function(pathname: string) {\n const m = re.exec(pathname);\n if (!m) return false;\n\n const { 0: path, index } = m;\n const params = Object.create(null);\n\n for (let i = 1; i < m.length; i++) {\n // tslint:disable-next-line\n if (m[i] === undefined) continue;\n\n const key = keys[i - 1];\n\n if (key.modifier === \"*\" || key.modifier === \"+\") {\n params[key.name] = m[i].split(key.prefix + key.suffix).map(value => {\n return decode(value, key);\n });\n } else {\n params[key.name] = decode(m[i], key);\n }\n }\n\n return { path, index, params };\n };\n}\n\n/**\n * Escape a regular expression string.\n */\nfunction escapeString(str: string) {\n return str.replace(/([.+*?=^!:${}()[\\]|/\\\\])/g, \"\\\\$1\");\n}\n\n/**\n * Get the flags for a regexp from the options.\n */\nfunction flags(options?: { sensitive?: boolean }) {\n return options && options.sensitive ? \"\" : \"i\";\n}\n\n/**\n * Metadata about a key.\n */\nexport interface Key {\n name: string | number;\n prefix: string;\n suffix: string;\n pattern: string;\n modifier: string;\n}\n\n/**\n * A token is a string (nothing special) or key metadata (capture group).\n */\nexport type Token = string | Key;\n\n/**\n * Pull out keys from a regexp.\n */\nfunction regexpToRegexp(path: RegExp, keys?: Key[]): RegExp {\n if (!keys) return path;\n\n const groupsRegex = /\\((?:\\?<(.*?)>)?(?!\\?)/g;\n\n let index = 0;\n let execResult = groupsRegex.exec(path.source);\n while (execResult) {\n keys.push({\n // Use parenthesized substring match if available, index otherwise\n name: execResult[1] || index++,\n prefix: \"\",\n suffix: \"\",\n modifier: \"\",\n pattern: \"\"\n });\n execResult = groupsRegex.exec(path.source);\n }\n\n return path;\n}\n\n/**\n * Transform an array into a regexp.\n */\nfunction arrayToRegexp(\n paths: Array,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions\n): RegExp {\n const parts = paths.map(path => pathToRegexp(path, keys, options).source);\n return new RegExp(`(?:${parts.join(\"|\")})`, flags(options));\n}\n\n/**\n * Create a path regexp from string input.\n */\nfunction stringToRegexp(\n path: string,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions\n) {\n return tokensToRegexp(parse(path, options), keys, options);\n}\n\nexport interface TokensToRegexpOptions {\n /**\n * When `true` the regexp will be case sensitive. (default: `false`)\n */\n sensitive?: boolean;\n /**\n * When `true` the regexp won't allow an optional trailing delimiter to match. (default: `false`)\n */\n strict?: boolean;\n /**\n * When `true` the regexp will match to the end of the string. (default: `true`)\n */\n end?: boolean;\n /**\n * When `true` the regexp will match from the beginning of the string. (default: `true`)\n */\n start?: boolean;\n /**\n * Sets the final character for non-ending optimistic matches. (default: `/`)\n */\n delimiter?: string;\n /**\n * List of characters that can also be \"end\" characters.\n */\n endsWith?: string;\n /**\n * Encode path tokens for use in the `RegExp`.\n */\n encode?: (value: string) => string;\n}\n\n/**\n * Expose a function for taking tokens and returning a RegExp.\n */\nexport function tokensToRegexp(\n tokens: Token[],\n keys?: Key[],\n options: TokensToRegexpOptions = {}\n) {\n const {\n strict = false,\n start = true,\n end = true,\n encode = (x: string) => x\n } = options;\n const endsWith = `[${escapeString(options.endsWith || \"\")}]|$`;\n const delimiter = `[${escapeString(options.delimiter || \"/#?\")}]`;\n let route = start ? \"^\" : \"\";\n\n // Iterate over the tokens and create our regexp string.\n for (const token of tokens) {\n if (typeof token === \"string\") {\n route += escapeString(encode(token));\n } else {\n const prefix = escapeString(encode(token.prefix));\n const suffix = escapeString(encode(token.suffix));\n\n if (token.pattern) {\n if (keys) keys.push(token);\n\n if (prefix || suffix) {\n if (token.modifier === \"+\" || token.modifier === \"*\") {\n const mod = token.modifier === \"*\" ? \"?\" : \"\";\n route += `(?:${prefix}((?:${token.pattern})(?:${suffix}${prefix}(?:${token.pattern}))*)${suffix})${mod}`;\n } else {\n route += `(?:${prefix}(${token.pattern})${suffix})${token.modifier}`;\n }\n } else {\n route += `(${token.pattern})${token.modifier}`;\n }\n } else {\n route += `(?:${prefix}${suffix})${token.modifier}`;\n }\n }\n }\n\n if (end) {\n if (!strict) route += `${delimiter}?`;\n\n route += !options.endsWith ? \"$\" : `(?=${endsWith})`;\n } else {\n const endToken = tokens[tokens.length - 1];\n const isEndDelimited =\n typeof endToken === \"string\"\n ? delimiter.indexOf(endToken[endToken.length - 1]) > -1\n : // tslint:disable-next-line\n endToken === undefined;\n\n if (!strict) {\n route += `(?:${delimiter}(?=${endsWith}))?`;\n }\n\n if (!isEndDelimited) {\n route += `(?=${delimiter}|${endsWith})`;\n }\n }\n\n return new RegExp(route, flags(options));\n}\n\n/**\n * Supported `path-to-regexp` input types.\n */\nexport type Path = string | RegExp | Array;\n\n/**\n * Normalize the given path string, returning a regular expression.\n *\n * An empty array can be passed in for the keys, which will hold the\n * placeholder key descriptions. For example, using `/user/:id`, `keys` will\n * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.\n */\nexport function pathToRegexp(\n path: Path,\n keys?: Key[],\n options?: TokensToRegexpOptions & ParseOptions\n) {\n if (path instanceof RegExp) return regexpToRegexp(path, keys);\n if (Array.isArray(path)) return arrayToRegexp(path, keys, options);\n return stringToRegexp(path, keys, options);\n}\n", - "transpiled": "/**\n * Tokenize input string.\n */ function lexer(str) {\n const tokens = [];\n let i = 0;\n while(i < str.length){\n const char = str[i];\n if (char === \"*\" || char === \"+\" || char === \"?\") {\n tokens.push({\n type: \"MODIFIER\",\n index: i,\n value: str[i++]\n });\n continue;\n }\n if (char === \"\\\\\") {\n tokens.push({\n type: \"ESCAPED_CHAR\",\n index: i++,\n value: str[i++]\n });\n continue;\n }\n if (char === \"{\") {\n tokens.push({\n type: \"OPEN\",\n index: i,\n value: str[i++]\n });\n continue;\n }\n if (char === \"}\") {\n tokens.push({\n type: \"CLOSE\",\n index: i,\n value: str[i++]\n });\n continue;\n }\n if (char === \":\") {\n let name = \"\";\n let j = i + 1;\n while(j < str.length){\n const code = str.charCodeAt(j);\n if (// `0-9`\n (code >= 48 && code <= 57) || // `A-Z`\n (code >= 65 && code <= 90) || // `a-z`\n (code >= 97 && code <= 122) || // `_`\n code === 95) {\n name += str[j++];\n continue;\n }\n break;\n }\n if (!name) throw new TypeError(`Missing parameter name at ${i}`);\n tokens.push({\n type: \"NAME\",\n index: i,\n value: name\n });\n i = j;\n continue;\n }\n if (char === \"(\") {\n let count = 1;\n let pattern = \"\";\n let j = i + 1;\n if (str[j] === \"?\") {\n throw new TypeError(`Pattern cannot start with \"?\" at ${j}`);\n }\n while(j < str.length){\n if (str[j] === \"\\\\\") {\n pattern += str[j++] + str[j++];\n continue;\n }\n if (str[j] === \")\") {\n count--;\n if (count === 0) {\n j++;\n break;\n }\n } else if (str[j] === \"(\") {\n count++;\n if (str[j + 1] !== \"?\") {\n throw new TypeError(`Capturing groups are not allowed at ${j}`);\n }\n }\n pattern += str[j++];\n }\n if (count) throw new TypeError(`Unbalanced pattern at ${i}`);\n if (!pattern) throw new TypeError(`Missing pattern at ${i}`);\n tokens.push({\n type: \"PATTERN\",\n index: i,\n value: pattern\n });\n i = j;\n continue;\n }\n tokens.push({\n type: \"CHAR\",\n index: i,\n value: str[i++]\n });\n }\n tokens.push({\n type: \"END\",\n index: i,\n value: \"\"\n });\n return tokens;\n}\n/**\n * Parse a string for the raw tokens.\n */ export function parse(str, options = {\n}) {\n const tokens = lexer(str);\n const { prefixes =\"./\" } = options;\n const defaultPattern = `[^${escapeString(options.delimiter || \"/#?\")}]+?`;\n const result = [];\n let key = 0;\n let i = 0;\n let path = \"\";\n const tryConsume = (type)=>{\n if (i < tokens.length && tokens[i].type === type) return tokens[i++].value;\n };\n const mustConsume = (type)=>{\n const value = tryConsume(type);\n if (value !== undefined) return value;\n const { type: nextType , index } = tokens[i];\n throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}`);\n };\n const consumeText = ()=>{\n let result = \"\";\n let value;\n // tslint:disable-next-line\n while(value = tryConsume(\"CHAR\") || tryConsume(\"ESCAPED_CHAR\")){\n result += value;\n }\n return result;\n };\n while(i < tokens.length){\n const char = tryConsume(\"CHAR\");\n const name = tryConsume(\"NAME\");\n const pattern = tryConsume(\"PATTERN\");\n if (name || pattern) {\n let prefix = char || \"\";\n if (prefixes.indexOf(prefix) === -1) {\n path += prefix;\n prefix = \"\";\n }\n if (path) {\n result.push(path);\n path = \"\";\n }\n result.push({\n name: name || key++,\n prefix,\n suffix: \"\",\n pattern: pattern || defaultPattern,\n modifier: tryConsume(\"MODIFIER\") || \"\"\n });\n continue;\n }\n const value = char || tryConsume(\"ESCAPED_CHAR\");\n if (value) {\n path += value;\n continue;\n }\n if (path) {\n result.push(path);\n path = \"\";\n }\n const open = tryConsume(\"OPEN\");\n if (open) {\n const prefix = consumeText();\n const name = tryConsume(\"NAME\") || \"\";\n const pattern = tryConsume(\"PATTERN\") || \"\";\n const suffix = consumeText();\n mustConsume(\"CLOSE\");\n result.push({\n name: name || (pattern ? key++ : \"\"),\n pattern: name && !pattern ? defaultPattern : pattern,\n prefix,\n suffix,\n modifier: tryConsume(\"MODIFIER\") || \"\"\n });\n continue;\n }\n mustConsume(\"END\");\n }\n return result;\n}\n/**\n * Compile a string to a template function for the path.\n */ export function compile(str, options) {\n return tokensToFunction(parse(str, options), options);\n}\n/**\n * Expose a method for transforming tokens into the path function.\n */ export function tokensToFunction(tokens, options = {\n}) {\n const reFlags = flags(options);\n const { encode =(x)=>x\n , validate =true } = options;\n // Compile all the tokens into regexps.\n const matches = tokens.map((token)=>{\n if (typeof token === \"object\") {\n return new RegExp(`^(?:${token.pattern})$`, reFlags);\n }\n });\n return (data)=>{\n let path = \"\";\n for(let i = 0; i < tokens.length; i++){\n const token = tokens[i];\n if (typeof token === \"string\") {\n path += token;\n continue;\n }\n const value = data ? data[token.name] : undefined;\n const optional = token.modifier === \"?\" || token.modifier === \"*\";\n const repeat = token.modifier === \"*\" || token.modifier === \"+\";\n if (Array.isArray(value)) {\n if (!repeat) {\n throw new TypeError(`Expected \"${token.name}\" to not repeat, but got an array`);\n }\n if (value.length === 0) {\n if (optional) continue;\n throw new TypeError(`Expected \"${token.name}\" to not be empty`);\n }\n for(let j = 0; j < value.length; j++){\n const segment = encode(value[j], token);\n if (validate && !matches[i].test(segment)) {\n throw new TypeError(`Expected all \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`);\n }\n path += token.prefix + segment + token.suffix;\n }\n continue;\n }\n if (typeof value === \"string\" || typeof value === \"number\") {\n const segment = encode(String(value), token);\n if (validate && !matches[i].test(segment)) {\n throw new TypeError(`Expected \"${token.name}\" to match \"${token.pattern}\", but got \"${segment}\"`);\n }\n path += token.prefix + segment + token.suffix;\n continue;\n }\n if (optional) continue;\n const typeOfMessage = repeat ? \"an array\" : \"a string\";\n throw new TypeError(`Expected \"${token.name}\" to be ${typeOfMessage}`);\n }\n return path;\n };\n}\n/**\n * Create path match function from `path-to-regexp` spec.\n */ export function match(str, options) {\n const keys = [];\n const re = pathToRegexp(str, keys, options);\n return regexpToFunction(re, keys, options);\n}\n/**\n * Create a path match function from `path-to-regexp` output.\n */ export function regexpToFunction(re, keys, options = {\n}) {\n const { decode =(x)=>x\n } = options;\n return function(pathname) {\n const m = re.exec(pathname);\n if (!m) return false;\n const { 0: path , index } = m;\n const params = Object.create(null);\n for(let i = 1; i < m.length; i++){\n // tslint:disable-next-line\n if (m[i] === undefined) continue;\n const key = keys[i - 1];\n if (key.modifier === \"*\" || key.modifier === \"+\") {\n params[key.name] = m[i].split(key.prefix + key.suffix).map((value)=>{\n return decode(value, key);\n });\n } else {\n params[key.name] = decode(m[i], key);\n }\n }\n return {\n path,\n index,\n params\n };\n };\n}\n/**\n * Escape a regular expression string.\n */ function escapeString(str) {\n return str.replace(/([.+*?=^!:${}()[\\]|/\\\\])/g, \"\\\\$1\");\n}\n/**\n * Get the flags for a regexp from the options.\n */ function flags(options) {\n return options && options.sensitive ? \"\" : \"i\";\n}\n/**\n * Pull out keys from a regexp.\n */ function regexpToRegexp(path, keys) {\n if (!keys) return path;\n const groupsRegex = /\\((?:\\?<(.*?)>)?(?!\\?)/g;\n let index = 0;\n let execResult = groupsRegex.exec(path.source);\n while(execResult){\n keys.push({\n // Use parenthesized substring match if available, index otherwise\n name: execResult[1] || index++,\n prefix: \"\",\n suffix: \"\",\n modifier: \"\",\n pattern: \"\"\n });\n execResult = groupsRegex.exec(path.source);\n }\n return path;\n}\n/**\n * Transform an array into a regexp.\n */ function arrayToRegexp(paths, keys, options) {\n const parts = paths.map((path)=>pathToRegexp(path, keys, options).source\n );\n return new RegExp(`(?:${parts.join(\"|\")})`, flags(options));\n}\n/**\n * Create a path regexp from string input.\n */ function stringToRegexp(path, keys, options) {\n return tokensToRegexp(parse(path, options), keys, options);\n}\n/**\n * Expose a function for taking tokens and returning a RegExp.\n */ export function tokensToRegexp(tokens, keys, options = {\n}) {\n const { strict =false , start =true , end =true , encode =(x)=>x\n } = options;\n const endsWith = `[${escapeString(options.endsWith || \"\")}]|$`;\n const delimiter = `[${escapeString(options.delimiter || \"/#?\")}]`;\n let route = start ? \"^\" : \"\";\n // Iterate over the tokens and create our regexp string.\n for (const token of tokens){\n if (typeof token === \"string\") {\n route += escapeString(encode(token));\n } else {\n const prefix = escapeString(encode(token.prefix));\n const suffix = escapeString(encode(token.suffix));\n if (token.pattern) {\n if (keys) keys.push(token);\n if (prefix || suffix) {\n if (token.modifier === \"+\" || token.modifier === \"*\") {\n const mod = token.modifier === \"*\" ? \"?\" : \"\";\n route += `(?:${prefix}((?:${token.pattern})(?:${suffix}${prefix}(?:${token.pattern}))*)${suffix})${mod}`;\n } else {\n route += `(?:${prefix}(${token.pattern})${suffix})${token.modifier}`;\n }\n } else {\n route += `(${token.pattern})${token.modifier}`;\n }\n } else {\n route += `(?:${prefix}${suffix})${token.modifier}`;\n }\n }\n }\n if (end) {\n if (!strict) route += `${delimiter}?`;\n route += !options.endsWith ? \"$\" : `(?=${endsWith})`;\n } else {\n const endToken = tokens[tokens.length - 1];\n const isEndDelimited = typeof endToken === \"string\" ? delimiter.indexOf(endToken[endToken.length - 1]) > -1 : endToken === undefined;\n if (!strict) {\n route += `(?:${delimiter}(?=${endsWith}))?`;\n }\n if (!isEndDelimited) {\n route += `(?=${delimiter}|${endsWith})`;\n }\n }\n return new RegExp(route, flags(options));\n}\n/**\n * Normalize the given path string, returning a regular expression.\n *\n * An empty array can be passed in for the keys, which will hold the\n * placeholder key descriptions. For example, using `/user/:id`, `keys` will\n * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.\n */ export function pathToRegexp(path, keys, options) {\n if (path instanceof RegExp) return regexpToRegexp(path, keys);\n if (Array.isArray(path)) return arrayToRegexp(path, keys, options);\n return stringToRegexp(path, keys, options);\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L3BhdGhfdG9fcmVnZXhwQHY2LjIuMC9pbmRleC50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUJBLEVBRUcsQUFGSDs7Q0FFRyxBQUZILEVBRUcsVUFDTSxLQUFLLENBQUMsR0FBVyxFQUFjLENBQUM7SUFDdkMsS0FBSyxDQUFDLE1BQU0sR0FBZSxDQUFDLENBQUM7SUFDN0IsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDO1VBRUYsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUUsQ0FBQztRQUN0QixLQUFLLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBRWxCLEVBQUUsRUFBRSxJQUFJLEtBQUssQ0FBRyxNQUFJLElBQUksS0FBSyxDQUFHLE1BQUksSUFBSSxLQUFLLENBQUcsSUFBRSxDQUFDO1lBQ2pELE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFBQyxJQUFJLEVBQUUsQ0FBVTtnQkFBRSxLQUFLLEVBQUUsQ0FBQztnQkFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFBSSxDQUFDO1lBQzNELFFBQVE7UUFDVixDQUFDO1FBRUQsRUFBRSxFQUFFLElBQUksS0FBSyxDQUFJLEtBQUUsQ0FBQztZQUNsQixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQUMsSUFBSSxFQUFFLENBQWM7Z0JBQUUsS0FBSyxFQUFFLENBQUM7Z0JBQUksS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQUksQ0FBQztZQUNqRSxRQUFRO1FBQ1YsQ0FBQztRQUVELEVBQUUsRUFBRSxJQUFJLEtBQUssQ0FBRyxJQUFFLENBQUM7WUFDakIsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUFDLElBQUksRUFBRSxDQUFNO2dCQUFFLEtBQUssRUFBRSxDQUFDO2dCQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztZQUFJLENBQUM7WUFDdkQsUUFBUTtRQUNWLENBQUM7UUFFRCxFQUFFLEVBQUUsSUFBSSxL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", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "file:///src/util/registry_utils.ts": { - "Source": { - "source": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */\n\nconst CDN_ENDPOINT = \"https://cdn.deno.land/\";\nconst API_ENDPOINT = \"https://api.deno.land/\";\n\nexport interface DirEntry {\n name: string;\n type: \"file\" | \"dir\" | \"symlink\";\n size?: number;\n target?: string;\n}\n\nexport interface Entry extends DirEntry {\n path?: string;\n}\n\nexport function getSourceURL(\n module: string,\n version: string,\n path: string,\n): string {\n return encodeURI(`${CDN_ENDPOINT}${module}/versions/${version}/raw${path}`);\n}\n\nfunction pathJoin(...parts: string[]) {\n const replace = new RegExp(\"/{1,}\", \"g\");\n return parts.join(\"/\").replace(replace, \"/\");\n}\n\nexport function getRepositoryURL(\n meta: VersionMetaInfo,\n path: string,\n type = \"blob\",\n): string | undefined {\n switch (meta.uploadOptions.type) {\n case \"github\":\n return `https://github.com/${\n pathJoin(\n meta.uploadOptions.repository,\n type,\n meta.uploadOptions.ref,\n meta.uploadOptions.subdir ?? \"\",\n path,\n )\n }`;\n default:\n return undefined;\n }\n}\n\nexport interface VersionMetaInfo {\n uploadedAt: Date;\n directoryListing: DirListing[];\n uploadOptions: UploadOptions;\n}\n\nexport interface UploadOptions {\n type: \"github\";\n repository: string;\n subdir?: string;\n ref: string;\n}\n\nexport interface DirListing {\n path: string;\n type: \"dir\" | \"file\";\n size?: number;\n}\n\nexport async function getVersionMeta(\n module: string,\n version: string,\n): Promise {\n const url = `${CDN_ENDPOINT}${module}/versions/${\n encodeURIComponent(\n version,\n )\n }/meta/meta.json`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\",\n },\n });\n if (res.status === 403 || res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(\n `Got an error (${res.status}) while getting the directory listing:\\n${await res\n .text()}`,\n );\n }\n\n const meta = await res.json();\n if (!meta) return null;\n\n return {\n uploadedAt: new Date(meta.uploaded_at),\n directoryListing: meta.directory_listing,\n uploadOptions: meta.upload_options,\n };\n}\n\nexport interface VersionDeps {\n graph: DependencyGraph;\n}\n\nexport interface DependencyGraph {\n nodes: {\n [url: string]: {\n deps: string[];\n size: number;\n };\n };\n}\n\nexport async function getVersionDeps(\n module: string,\n version: string,\n): Promise {\n const url = `${CDN_ENDPOINT}${module}/versions/${\n encodeURIComponent(\n version,\n )\n }/meta/deps_v2.json`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\",\n },\n });\n if (res.status === 403 || res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(\n `Got an error (${res.status}) while getting the dependency information:\\n${await res\n .text()}`,\n );\n }\n const meta = await res.json();\n if (!meta) return null;\n return {\n graph: meta.graph,\n };\n}\n\nexport interface VersionInfo {\n latest: string;\n versions: string[];\n isLegacy: true;\n}\n\nexport async function getVersionList(\n module: string,\n): Promise {\n const url = `${CDN_ENDPOINT}${module}/meta/versions.json`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\",\n },\n });\n if (res.status === 403 || res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(\n `Got an error (${res.status}) while getting the version list:\\n${await res\n .text()}`,\n );\n }\n return res.json();\n}\n\nexport interface Module {\n name: string;\n description: string;\n star_count: string;\n}\n\nexport interface SearchResult extends Module {\n search_score: string;\n}\n\nexport async function listModules(\n page: number,\n limit: number,\n query: string,\n): Promise<{ results: SearchResult[]; totalCount: number } | null> {\n const url = `${API_ENDPOINT}modules?page=${page}&limit=${limit}&query=${\n encodeURIComponent(\n query,\n )\n }`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\",\n },\n });\n if (res.status !== 200) {\n throw Error(\n `Got an error (${res.status}) while getting the module list:\\n${await res\n .text()}`,\n );\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(\n `Got an error (${data.info}) while getting the module list:\\n${await res\n .text()}`,\n );\n }\n\n return { totalCount: data.data.total_count, results: data.data.results };\n}\n\nexport async function getModule(name: string): Promise {\n const url = `${API_ENDPOINT}modules/${encodeURIComponent(name)}`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\",\n },\n });\n if (res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(\n `Got an error (${res.status}) while getting the module ${name}:\\n${await res\n .text()}`,\n );\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(\n `Got an error (${data.info}) while getting the module ${name}:\\n${await res\n .text()}`,\n );\n }\n return data.data;\n}\n\nexport interface Build {\n id: string;\n options: {\n moduleName: string;\n type: string;\n repository: string;\n ref: string;\n version: string;\n subdir?: string;\n };\n status: string;\n message?: string;\n}\n\nexport async function getBuild(id: string): Promise {\n const url = `${API_ENDPOINT}builds/${id}`;\n const res = await fetch(url, { headers: { accept: \"application/json\" } });\n if (res.status !== 200) {\n throw Error(\n `Got an error (${res.status}) while getting the build info:\\n${await res\n .text()}`,\n );\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(\n `Got an error (${data.info}) while getting the build info:\\n${await res\n .text()}`,\n );\n }\n return data.data.build;\n}\n\nexport function parseNameVersion(nameVersion: string): [string, string] {\n const [name, ...version] = nameVersion.split(\"@\");\n return [name, version.join(\"@\")];\n}\n\nexport function parseQuery(\n queryRest: string[],\n): { name: string; version: string; path: string } {\n const [identifier, ...pathParts] = (queryRest as string[]) ?? [];\n const path = pathParts.length === 0 ? \"\" : `/${pathParts.join(\"/\")}`;\n const [name, version] = parseNameVersion(identifier ?? \"\");\n return { name, version, path };\n}\n\nconst markdownExtension = \"(?:markdown|mdown|mkdn|mdwn|mkd|md)\";\nconst orgExtension = \"org\";\nconst readmeBaseRegex = `readme(?:\\\\.(${markdownExtension}|${orgExtension}))?`;\n\nexport function fileTypeFromURL(filename: string): string | undefined {\n const f = filename.toLowerCase();\n if (f.endsWith(\".ts\")) {\n return \"typescript\";\n } else if (f.endsWith(\".js\") || f.endsWith(\".mjs\") || f.endsWith(\".cjs\")) {\n return \"javascript\";\n } else if (f.endsWith(\".tsx\")) {\n return \"tsx\";\n } else if (f.endsWith(\".jsx\")) {\n return \"jsx\";\n } else if (f.endsWith(\".json\")) {\n return \"json\";\n } else if (f.endsWith(\".toml\")) {\n return \"toml\";\n } else if (f.endsWith(\".lock\")) {\n return \"toml\";\n } else if (f.endsWith(\".rs\")) {\n return \"rust\";\n } else if (f.endsWith(\".py\")) {\n return \"python\";\n } else if (f.endsWith(\".wasm\")) {\n return \"wasm\";\n } else if (f.toLocaleLowerCase().endsWith(\"makefile\")) {\n return \"makefile\";\n } else if (f.endsWith(\".dockerfile\") || f.endsWith(\"dockerfile\")) {\n return \"dockerfile\";\n } else if (f.endsWith(\".yml\") || f.endsWith(\".yaml\")) {\n return \"yaml\";\n } else if (f.endsWith(\".htm\") || f.endsWith(\".html\")) {\n return \"html\";\n } else if (f.match(`\\\\.${markdownExtension}$`)) {\n return \"markdown\";\n } else if (f.match(`\\\\.${orgExtension}$`)) {\n return \"org\";\n } else if (f.match(/\\.(png|jpe?g|svg)/)) {\n return \"image\";\n }\n}\n\nexport function fileNameFromURL(url: string): string {\n const segments = decodeURI(url).split(\"/\");\n return segments[segments.length - 1];\n}\n\nexport function denoDocAvailableForURL(filename: string): boolean {\n const filetype = fileTypeFromURL(filename);\n switch (filetype) {\n case \"javascript\":\n case \"typescript\":\n case \"jsx\":\n case \"tsx\":\n return true;\n default:\n return false;\n }\n}\n\nexport function findRootReadme(\n directoryListing: DirListing[] | undefined,\n): DirEntry | undefined {\n const listing = directoryListing?.find((d) =>\n new RegExp(`^\\\\/(docs\\\\/|\\\\.github\\\\/)?${readmeBaseRegex}$`, \"i\").test(\n d.path,\n )\n );\n return listing\n ? {\n name: listing.path.substring(1),\n type: listing.type,\n size: listing.size,\n }\n : undefined;\n}\n\nexport function isReadme(filename: string): boolean {\n return new RegExp(`^${readmeBaseRegex}$`, \"i\").test(filename);\n}\n\nexport type Dep = { name: string; children: Dep[] };\n\nexport function graphToTree(\n graph: DependencyGraph,\n name: string,\n visited: string[] = [],\n): Dep | undefined {\n const dep = graph.nodes[name];\n if (dep === undefined) return undefined;\n visited.push(name);\n return {\n name,\n children: dep.deps\n .filter((n) => !visited.includes(n))\n .map((n) => graphToTree(graph, n, visited)!),\n };\n}\n\nexport function flattenGraph(\n graph: DependencyGraph,\n name: string,\n visited: string[] = [],\n): string[] | undefined {\n const dep = graph.nodes[name];\n if (dep === undefined) return undefined;\n visited.push(name);\n dep.deps\n .filter((n) => !visited.includes(n))\n .forEach((n) => flattenGraph(graph, n, visited)!);\n return visited;\n}\n\nfunction matchX(url: string) {\n const match = url.match(/^https:\\/\\/deno\\.land\\/x\\/([^/]+)(.+)$/);\n if (!match) return undefined;\n return {\n identifier: match[1],\n path: match[2],\n };\n}\n\nfunction matchStd(url: string) {\n const match = url.match(/^https:\\/\\/deno\\.land\\/(x\\/)?std(@([^/]+))?(.+)?$/);\n if (!match) return undefined;\n return {\n version: match[2],\n submodule: match[4],\n path: match[5],\n };\n}\n\nexport function listExternalDependencies(\n graph: DependencyGraph,\n name: string,\n): string[] | undefined {\n const visited = flattenGraph(graph, name);\n const denolandDeps = new Set();\n const nestlandDeps = new Set();\n const rawGithubDeps = new Set();\n const jspmDeps = new Set();\n const depJsDeps = new Set();\n const other = new Set();\n if (visited) {\n visited.forEach((dep) => {\n // Count /std only once\n const std = matchStd(dep);\n if (std) {\n denolandDeps.add(`https://deno.land/std${std.version ?? \"\"}`);\n return;\n }\n\n // Count each module on /x only once.\n const x = matchX(dep);\n if (x) {\n denolandDeps.add(`https://deno.land/x/${x.identifier}`);\n return;\n }\n\n // Count each module on nest only once.\n const nest = dep.match(/^https:\\/\\/x\\.nest\\.land\\/([^/]+)(.+)$/);\n if (nest) {\n nestlandDeps.add(`https://nest.land/packages/${nest[1]}`);\n return;\n }\n\n // Count each module on raw.githubusercontent.com only once.\n const rawGithub = dep.match(\n /^https:\\/\\/raw\\.githubusercontent\\.com\\/([^/]+)\\/([^/]+)\\/([^/]+)(.+)$/,\n );\n if (rawGithub) {\n rawGithubDeps.add(\n `https://github.com/${rawGithub[1]}/${rawGithub[2]}/tree/${\n rawGithub[3]\n }`,\n );\n return;\n }\n\n // Count each module on raw.githubusercontent.com only once.\n const jspm = dep.match(\n /^https:\\/\\/dev\\.jspm\\.io\\/(npm:)?(@([^/@]+)\\/([^/@]+)|([^/@]+))@(\\d\\.\\d\\.\\d)(.+)$/,\n );\n if (jspm) {\n jspmDeps.add(`https://dev.jspm.io/${jspm[2]}@${jspm[6]}`);\n return;\n }\n if (dep.startsWith(\"https://dev.jspm.io\")) return;\n\n // Count each module on cdn.depjs.com only once.\n const depJs = dep.match(/^https:\\/\\/cdn\\.depjs\\.com\\/([^/]+)(.+)$/);\n if (depJs) {\n depJsDeps.add(`https://cdn.depjs.com/${depJs[1]}`);\n return;\n }\n\n // Ignore pika internal imports\n if (dep.startsWith(\"https://cdn.pika.dev/-/\")) return;\n\n other.add(dep);\n });\n const thisStd = matchStd(name);\n if (thisStd) {\n denolandDeps.delete(`https://deno.land/std${thisStd.version ?? \"\"}`);\n }\n const thisX = matchX(name);\n if (thisX) {\n denolandDeps.delete(`https://deno.land/x/${thisX.identifier}`);\n }\n return [\n ...denolandDeps,\n ...nestlandDeps,\n ...rawGithubDeps,\n ...jspmDeps,\n ...depJsDeps,\n ...other,\n ].map((url) =>\n url.replace(\"https://deno.land/x/std\", \"https://deno.land/std\")\n );\n } else return undefined;\n}\n\nexport async function getStats(): Promise<\n {\n recently_added_modules: Array;\n recently_uploaded_versions: Array<{\n name: string;\n version: string;\n created_at: string;\n }>;\n } | null\n> {\n const url = `${API_ENDPOINT}stats`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\",\n },\n });\n if (res.status !== 200) {\n throw Error(\n `Got an error (${res.status}) while getting the stats:\\n${await res\n .text()}`,\n );\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(\n `Got an error (${data.info}) while getting the stats:\\n${await res\n .text()}`,\n );\n }\n\n return data.data;\n}\n\nexport function getBasePath({\n isStd,\n name,\n version,\n}: {\n isStd: boolean;\n name: string;\n version?: string;\n}): string {\n return `${isStd ? \"\" : \"/x\"}/${name}${\n version ? `@${encodeURIComponent(version)}` : \"\"\n }`;\n}\n", - "transpiled": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */ const CDN_ENDPOINT = \"https://cdn.deno.land/\";\nconst API_ENDPOINT = \"https://api.deno.land/\";\nexport function getSourceURL(module, version, path) {\n return encodeURI(`${CDN_ENDPOINT}${module}/versions/${version}/raw${path}`);\n}\nfunction pathJoin(...parts) {\n const replace = new RegExp(\"/{1,}\", \"g\");\n return parts.join(\"/\").replace(replace, \"/\");\n}\nexport function getRepositoryURL(meta, path, type = \"blob\") {\n switch(meta.uploadOptions.type){\n case \"github\":\n return `https://github.com/${pathJoin(meta.uploadOptions.repository, type, meta.uploadOptions.ref, meta.uploadOptions.subdir ?? \"\", path)}`;\n default:\n return undefined;\n }\n}\nexport async function getVersionMeta(module, version) {\n const url = `${CDN_ENDPOINT}${module}/versions/${encodeURIComponent(version)}/meta/meta.json`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\"\n }\n });\n if (res.status === 403 || res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(`Got an error (${res.status}) while getting the directory listing:\\n${await res.text()}`);\n }\n const meta = await res.json();\n if (!meta) return null;\n return {\n uploadedAt: new Date(meta.uploaded_at),\n directoryListing: meta.directory_listing,\n uploadOptions: meta.upload_options\n };\n}\nexport async function getVersionDeps(module, version) {\n const url = `${CDN_ENDPOINT}${module}/versions/${encodeURIComponent(version)}/meta/deps_v2.json`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\"\n }\n });\n if (res.status === 403 || res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(`Got an error (${res.status}) while getting the dependency information:\\n${await res.text()}`);\n }\n const meta = await res.json();\n if (!meta) return null;\n return {\n graph: meta.graph\n };\n}\nexport async function getVersionList(module) {\n const url = `${CDN_ENDPOINT}${module}/meta/versions.json`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\"\n }\n });\n if (res.status === 403 || res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(`Got an error (${res.status}) while getting the version list:\\n${await res.text()}`);\n }\n return res.json();\n}\nexport async function listModules(page, limit, query) {\n const url = `${API_ENDPOINT}modules?page=${page}&limit=${limit}&query=${encodeURIComponent(query)}`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\"\n }\n });\n if (res.status !== 200) {\n throw Error(`Got an error (${res.status}) while getting the module list:\\n${await res.text()}`);\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(`Got an error (${data.info}) while getting the module list:\\n${await res.text()}`);\n }\n return {\n totalCount: data.data.total_count,\n results: data.data.results\n };\n}\nexport async function getModule(name) {\n const url = `${API_ENDPOINT}modules/${encodeURIComponent(name)}`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\"\n }\n });\n if (res.status === 404) return null;\n if (res.status !== 200) {\n throw Error(`Got an error (${res.status}) while getting the module ${name}:\\n${await res.text()}`);\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(`Got an error (${data.info}) while getting the module ${name}:\\n${await res.text()}`);\n }\n return data.data;\n}\nexport async function getBuild(id) {\n const url = `${API_ENDPOINT}builds/${id}`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\"\n }\n });\n if (res.status !== 200) {\n throw Error(`Got an error (${res.status}) while getting the build info:\\n${await res.text()}`);\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(`Got an error (${data.info}) while getting the build info:\\n${await res.text()}`);\n }\n return data.data.build;\n}\nexport function parseNameVersion(nameVersion) {\n const [name, ...version] = nameVersion.split(\"@\");\n return [\n name,\n version.join(\"@\")\n ];\n}\nexport function parseQuery(queryRest) {\n const [identifier, ...pathParts] = queryRest ?? [];\n const path = pathParts.length === 0 ? \"\" : `/${pathParts.join(\"/\")}`;\n const [name, version] = parseNameVersion(identifier ?? \"\");\n return {\n name,\n version,\n path\n };\n}\nconst markdownExtension = \"(?:markdown|mdown|mkdn|mdwn|mkd|md)\";\nconst orgExtension = \"org\";\nconst readmeBaseRegex = `readme(?:\\\\.(${markdownExtension}|${orgExtension}))?`;\nexport function fileTypeFromURL(filename) {\n const f = filename.toLowerCase();\n if (f.endsWith(\".ts\")) {\n return \"typescript\";\n } else if (f.endsWith(\".js\") || f.endsWith(\".mjs\") || f.endsWith(\".cjs\")) {\n return \"javascript\";\n } else if (f.endsWith(\".tsx\")) {\n return \"tsx\";\n } else if (f.endsWith(\".jsx\")) {\n return \"jsx\";\n } else if (f.endsWith(\".json\")) {\n return \"json\";\n } else if (f.endsWith(\".toml\")) {\n return \"toml\";\n } else if (f.endsWith(\".lock\")) {\n return \"toml\";\n } else if (f.endsWith(\".rs\")) {\n return \"rust\";\n } else if (f.endsWith(\".py\")) {\n return \"python\";\n } else if (f.endsWith(\".wasm\")) {\n return \"wasm\";\n } else if (f.toLocaleLowerCase().endsWith(\"makefile\")) {\n return \"makefile\";\n } else if (f.endsWith(\".dockerfile\") || f.endsWith(\"dockerfile\")) {\n return \"dockerfile\";\n } else if (f.endsWith(\".yml\") || f.endsWith(\".yaml\")) {\n return \"yaml\";\n } else if (f.endsWith(\".htm\") || f.endsWith(\".html\")) {\n return \"html\";\n } else if (f.match(`\\\\.${markdownExtension}$`)) {\n return \"markdown\";\n } else if (f.match(`\\\\.${orgExtension}$`)) {\n return \"org\";\n } else if (f.match(/\\.(png|jpe?g|svg)/)) {\n return \"image\";\n }\n}\nexport function fileNameFromURL(url) {\n const segments = decodeURI(url).split(\"/\");\n return segments[segments.length - 1];\n}\nexport function denoDocAvailableForURL(filename) {\n const filetype = fileTypeFromURL(filename);\n switch(filetype){\n case \"javascript\":\n case \"typescript\":\n case \"jsx\":\n case \"tsx\":\n return true;\n default:\n return false;\n }\n}\nexport function findRootReadme(directoryListing) {\n const listing = directoryListing?.find((d)=>new RegExp(`^\\\\/(docs\\\\/|\\\\.github\\\\/)?${readmeBaseRegex}$`, \"i\").test(d.path)\n );\n return listing ? {\n name: listing.path.substring(1),\n type: listing.type,\n size: listing.size\n } : undefined;\n}\nexport function isReadme(filename) {\n return new RegExp(`^${readmeBaseRegex}$`, \"i\").test(filename);\n}\nexport function graphToTree(graph, name, visited = []) {\n const dep = graph.nodes[name];\n if (dep === undefined) return undefined;\n visited.push(name);\n return {\n name,\n children: dep.deps.filter((n)=>!visited.includes(n)\n ).map((n)=>graphToTree(graph, n, visited)\n )\n };\n}\nexport function flattenGraph(graph, name, visited = []) {\n const dep = graph.nodes[name];\n if (dep === undefined) return undefined;\n visited.push(name);\n dep.deps.filter((n)=>!visited.includes(n)\n ).forEach((n)=>flattenGraph(graph, n, visited)\n );\n return visited;\n}\nfunction matchX(url) {\n const match = url.match(/^https:\\/\\/deno\\.land\\/x\\/([^/]+)(.+)$/);\n if (!match) return undefined;\n return {\n identifier: match[1],\n path: match[2]\n };\n}\nfunction matchStd(url) {\n const match = url.match(/^https:\\/\\/deno\\.land\\/(x\\/)?std(@([^/]+))?(.+)?$/);\n if (!match) return undefined;\n return {\n version: match[2],\n submodule: match[4],\n path: match[5]\n };\n}\nexport function listExternalDependencies(graph, name) {\n const visited = flattenGraph(graph, name);\n const denolandDeps = new Set();\n const nestlandDeps = new Set();\n const rawGithubDeps = new Set();\n const jspmDeps = new Set();\n const depJsDeps = new Set();\n const other = new Set();\n if (visited) {\n visited.forEach((dep)=>{\n // Count /std only once\n const std = matchStd(dep);\n if (std) {\n denolandDeps.add(`https://deno.land/std${std.version ?? \"\"}`);\n return;\n }\n // Count each module on /x only once.\n const x = matchX(dep);\n if (x) {\n denolandDeps.add(`https://deno.land/x/${x.identifier}`);\n return;\n }\n // Count each module on nest only once.\n const nest = dep.match(/^https:\\/\\/x\\.nest\\.land\\/([^/]+)(.+)$/);\n if (nest) {\n nestlandDeps.add(`https://nest.land/packages/${nest[1]}`);\n return;\n }\n // Count each module on raw.githubusercontent.com only once.\n const rawGithub = dep.match(/^https:\\/\\/raw\\.githubusercontent\\.com\\/([^/]+)\\/([^/]+)\\/([^/]+)(.+)$/);\n if (rawGithub) {\n rawGithubDeps.add(`https://github.com/${rawGithub[1]}/${rawGithub[2]}/tree/${rawGithub[3]}`);\n return;\n }\n // Count each module on raw.githubusercontent.com only once.\n const jspm = dep.match(/^https:\\/\\/dev\\.jspm\\.io\\/(npm:)?(@([^/@]+)\\/([^/@]+)|([^/@]+))@(\\d\\.\\d\\.\\d)(.+)$/);\n if (jspm) {\n jspmDeps.add(`https://dev.jspm.io/${jspm[2]}@${jspm[6]}`);\n return;\n }\n if (dep.startsWith(\"https://dev.jspm.io\")) return;\n // Count each module on cdn.depjs.com only once.\n const depJs = dep.match(/^https:\\/\\/cdn\\.depjs\\.com\\/([^/]+)(.+)$/);\n if (depJs) {\n depJsDeps.add(`https://cdn.depjs.com/${depJs[1]}`);\n return;\n }\n // Ignore pika internal imports\n if (dep.startsWith(\"https://cdn.pika.dev/-/\")) return;\n other.add(dep);\n });\n const thisStd = matchStd(name);\n if (thisStd) {\n denolandDeps.delete(`https://deno.land/std${thisStd.version ?? \"\"}`);\n }\n const thisX = matchX(name);\n if (thisX) {\n denolandDeps.delete(`https://deno.land/x/${thisX.identifier}`);\n }\n return [\n ...denolandDeps,\n ...nestlandDeps,\n ...rawGithubDeps,\n ...jspmDeps,\n ...depJsDeps,\n ...other, \n ].map((url)=>url.replace(\"https://deno.land/x/std\", \"https://deno.land/std\")\n );\n } else return undefined;\n}\nexport async function getStats() {\n const url = `${API_ENDPOINT}stats`;\n const res = await fetch(url, {\n headers: {\n accept: \"application/json\"\n }\n });\n if (res.status !== 200) {\n throw Error(`Got an error (${res.status}) while getting the stats:\\n${await res.text()}`);\n }\n const data = await res.json();\n if (!data.success) {\n throw Error(`Got an error (${data.info}) while getting the stats:\\n${await res.text()}`);\n }\n return data.data;\n}\nexport function getBasePath({ isStd , name , version }) {\n return `${isStd ? \"\" : \"/x\"}/${name}${version ? `@${encodeURIComponent(version)}` : \"\"}`;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxmaWxlOi8vL3NyYy91dGlsL3JlZ2lzdHJ5X3V0aWxzLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQUF3RSxBQUF4RSxvRUFBd0UsQUFBeEUsRUFBd0UsQ0FFeEUsS0FBSyxDQUFDLFlBQVksR0FBRyxDQUF3QjtBQUM3QyxLQUFLLENBQUMsWUFBWSxHQUFHLENBQXdCO0FBYTdDLE1BQU0sVUFBVSxZQUFZLENBQzFCLE1BQWMsRUFDZCxPQUFlLEVBQ2YsSUFBWSxFQUNKLENBQUM7SUFDVCxNQUFNLENBQUMsU0FBUyxJQUFJLFlBQVksR0FBRyxNQUFNLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSTtBQUMxRSxDQUFDO1NBRVEsUUFBUSxJQUFJLEtBQUssRUFBWSxDQUFDO0lBQ3JDLEtBQUssQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFPLFFBQUUsQ0FBRztJQUN2QyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFHLElBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFHO0FBQzdDLENBQUM7QUFFRCxNQUFNLFVBQVUsZ0JBQWdCLENBQzlCLElBQXFCLEVBQ3JCLElBQVksRUFDWixJQUFJLEdBQUcsQ0FBTSxPQUNPLENBQUM7SUFDckIsTUFBTSxDQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSTtRQUM3QixJQUFJLENBQUMsQ0FBUTtZQUNYLE1BQU0sRUFBRSxtQkFBbUIsRUFDekIsUUFBUSxDQUNOLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUM3QixJQUFJLEVBQ0osSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQ3RCLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxJQUFJLENBQUUsR0FDL0IsSUFBSTs7WUFJUixNQUFNLENBQUMsU0FBUzs7QUFFdEIsQ0FBQztBQXFCRCxNQUFNLGdCQUFnQixjQUFjLENBQ2xDLE1BQWMsRUFDZCxPQUFlLEVBQ2tCLENBQUM7SUFDbEMs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", - "content_type": null, - "deps": [] - } - }, - "https://cdn.esm.sh/v64/twas@2.1.2/deno/twas.js": { - "Source": { - "source": "/* esm.sh - esbuild bundle(twas@2.1.2) deno production */\nvar t=function(a,o){return o>=a?Math.floor(o/a):0};function s(a,o){o||(o=Date.now());var e=(o-a)/1e3,h=t(60,e),u=t(60,h),f=t(24,u),l=t(7,f),i=t(30,f),c=t(12,i),r=c,n=\"year\";if(e<=1)return\"just now\";c>0?(r=c,n=\"year\"):i>0?(r=i,n=\"month\"):l>0?(r=l,n=\"week\"):f>0?(r=f,n=\"day\"):u>0?(r=u,n=\"hour\"):h>0?(r=h,n=\"minute\"):e>0&&(r=e,n=\"second\");var d=Math.floor(r);return(d===1?r===u?\"an\":\"a\":d)+\" \"+n+(d>1?\"s\":\"\")+\" ago\"}export{s as default};\n", - "transpiled": null, - "content_type": "text/javascript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.120.0/async/deferred.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n// TODO(ry) It'd be better to make Deferred a class that inherits from\n// Promise, rather than an interface. This is possible in ES2016, however\n// typescript produces broken code when targeting ES5 code.\n// See https://github.com/Microsoft/TypeScript/issues/15202\n// At the time of writing, the github issue is closed but the problem remains.\nexport interface Deferred extends Promise {\n readonly state: \"pending\" | \"fulfilled\" | \"rejected\";\n resolve(value?: T | PromiseLike): void;\n // deno-lint-ignore no-explicit-any\n reject(reason?: any): void;\n}\n\n/** Creates a Promise with the `reject` and `resolve` functions\n * placed as methods on the promise object itself. It allows you to do:\n *\n * ```ts\n * import { deferred } from \"./deferred.ts\";\n *\n * const p = deferred();\n * // ...\n * p.resolve(42);\n * ```\n */\nexport function deferred(): Deferred {\n let methods;\n let state = \"pending\";\n const promise = new Promise((resolve, reject): void => {\n methods = {\n async resolve(value: T | PromiseLike) {\n await value;\n state = \"fulfilled\";\n resolve(value);\n },\n // deno-lint-ignore no-explicit-any\n reject(reason?: any) {\n state = \"rejected\";\n reject(reason);\n },\n };\n });\n Object.defineProperty(promise, \"state\", { get: () => state });\n return Object.assign(promise, methods) as Deferred;\n}\n", - "transpiled": "/** Creates a Promise with the `reject` and `resolve` functions\n * placed as methods on the promise object itself. It allows you to do:\n *\n * ```ts\n * import { deferred } from \"./deferred.ts\";\n *\n * const p = deferred();\n * // ...\n * p.resolve(42);\n * ```\n */ export function deferred() {\n let methods;\n let state = \"pending\";\n const promise = new Promise((resolve, reject)=>{\n methods = {\n async resolve (value) {\n await value;\n state = \"fulfilled\";\n resolve(value);\n },\n // deno-lint-ignore no-explicit-any\n reject (reason) {\n state = \"rejected\";\n reject(reason);\n }\n };\n });\n Object.defineProperty(promise, \"state\", {\n get: ()=>state\n });\n return Object.assign(promise, methods);\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy9kZWZlcnJlZC50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBYUEsRUFVRyxBQVZIOzs7Ozs7Ozs7O0NBVUcsQUFWSCxFQVVHLENBQ0gsTUFBTSxVQUFVLFFBQVEsR0FBbUIsQ0FBQztJQUMxQyxHQUFHLENBQUMsT0FBTztJQUNYLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBUztJQUNyQixLQUFLLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQUssT0FBTyxFQUFFLE1BQU0sR0FBVyxDQUFDO1FBQ3pELE9BQU8sR0FBRyxDQUFDO2tCQUNILE9BQU8sRUFBQyxLQUF5QixFQUFFLENBQUM7Z0JBQ3hDLEtBQUssQ0FBQyxLQUFLO2dCQUNYLEtBQUssR0FBRyxDQUFXO2dCQUNuQixPQUFPLENBQUMsS0FBSztZQUNmLENBQUM7WUFDRCxFQUFtQyxBQUFuQyxpQ0FBbUM7WUFDbkMsTUFBTSxFQUFDLE1BQVksRUFBRSxDQUFDO2dCQUNwQixLQUFLLEdBQUcsQ0FBVTtnQkFDbEIsTUFBTSxDQUFDLE1BQU07WUFDZixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFPLFFBQUUsQ0FBQztRQUFDLEdBQUcsTUFBUSxLQUFLO0lBQUMsQ0FBQztJQUM1RCxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsT0FBTztBQUN2QyxDQUFDIn0=", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.108.0/async/deadline.ts": { - "Source": { - "source": "import { deferred } from \"./deferred.ts\";\n\nexport class DeadlineError extends Error {\n constructor() {\n super(\"Deadline\");\n this.name = \"DeadlineError\";\n }\n}\n\n/**\n * Create a promise which will be rejected with DeadlineError when a given delay is exceeded.\n */\nexport function deadline(p: Promise, delay: number): Promise {\n const d = deferred();\n const t = setTimeout(() => d.reject(new DeadlineError()), delay);\n return Promise.race([p, d]).finally(() => clearTimeout(t));\n}\n", - "transpiled": "import { deferred } from \"./deferred.ts\";\nexport class DeadlineError extends Error {\n constructor(){\n super(\"Deadline\");\n this.name = \"DeadlineError\";\n }\n}\n/**\n * Create a promise which will be rejected with DeadlineError when a given delay is exceeded.\n */ export function deadline(p, delay) {\n const d = deferred();\n const t = setTimeout(()=>d.reject(new DeadlineError())\n , delay);\n return Promise.race([\n p,\n d\n ]).finally(()=>clearTimeout(t)\n );\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy9kZWFkbGluZS50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxHQUFHLFFBQVEsUUFBUSxDQUFlO0FBRXhDLE1BQU0sT0FBTyxhQUFhLFNBQVMsS0FBSztpQkFDeEIsQ0FBQztRQUNiLEtBQUssQ0FBQyxDQUFVO1FBQ2hCLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBZTtJQUM3QixDQUFDOztBQUdILEVBRUcsQUFGSDs7Q0FFRyxBQUZILEVBRUcsQ0FDSCxNQUFNLFVBQVUsUUFBUSxDQUFJLENBQWEsRUFBRSxLQUFhLEVBQWMsQ0FBQztJQUNyRSxLQUFLLENBQUMsQ0FBQyxHQUFHLFFBQVE7SUFDbEIsS0FBSyxDQUFDLENBQUMsR0FBRyxVQUFVLEtBQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsYUFBYTtNQUFLLEtBQUs7SUFDL0QsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUFBLENBQUM7UUFBRSxDQUFDO0lBQUEsQ0FBQyxFQUFFLE9BQU8sS0FBTyxZQUFZLENBQUMsQ0FBQzs7QUFDMUQsQ0FBQyJ9", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/std@0.108.0/async/deferred.ts"] - } - }, - "https://deno.land/std@0.120.0/async/tee.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n// Utility for representing n-tuple\ntype Tuple = N extends N\n ? number extends N ? T[] : TupleOf\n : never;\ntype TupleOf = R[\"length\"] extends N\n ? R\n : TupleOf;\n\ninterface QueueNode {\n value: T;\n next: QueueNode | undefined;\n}\n\nclass Queue {\n #source: AsyncIterator;\n #queue: QueueNode;\n head: QueueNode;\n\n done: boolean;\n\n constructor(iterable: AsyncIterable) {\n this.#source = iterable[Symbol.asyncIterator]();\n this.#queue = {\n value: undefined!,\n next: undefined,\n };\n this.head = this.#queue;\n this.done = false;\n }\n\n async next(): Promise {\n const result = await this.#source.next();\n if (!result.done) {\n const nextNode: QueueNode = {\n value: result.value,\n next: undefined,\n };\n this.#queue.next = nextNode;\n this.#queue = nextNode;\n } else {\n this.done = true;\n }\n }\n}\n\n/**\n * Branches the given async iterable into the n branches.\n *\n * Example:\n *\n * ```ts\n * import { tee } from \"./tee.ts\";\n *\n * const gen = async function* gen() {\n * yield 1;\n * yield 2;\n * yield 3;\n * }\n *\n * const [branch1, branch2] = tee(gen());\n *\n * (async () => {\n * for await (const n of branch1) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n *\n * (async () => {\n * for await (const n of branch2) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n * ```\n */\nexport function tee(\n iterable: AsyncIterable,\n n: N = 2 as N,\n): Tuple, N> {\n const queue = new Queue(iterable);\n\n async function* generator(): AsyncGenerator {\n let buffer = queue.head;\n while (true) {\n if (buffer.next) {\n buffer = buffer.next;\n yield buffer.value;\n } else if (queue.done) {\n return;\n } else {\n await queue.next();\n }\n }\n }\n\n const branches = Array.from({ length: n }).map(\n () => generator(),\n ) as Tuple<\n AsyncIterable,\n N\n >;\n return branches;\n}\n", - "transpiled": "class Queue {\n #source;\n #queue;\n head;\n done;\n constructor(iterable){\n this.#source = iterable[Symbol.asyncIterator]();\n this.#queue = {\n value: undefined,\n next: undefined\n };\n this.head = this.#queue;\n this.done = false;\n }\n async next() {\n const result = await this.#source.next();\n if (!result.done) {\n const nextNode = {\n value: result.value,\n next: undefined\n };\n this.#queue.next = nextNode;\n this.#queue = nextNode;\n } else {\n this.done = true;\n }\n }\n}\n/**\n * Branches the given async iterable into the n branches.\n *\n * Example:\n *\n * ```ts\n * import { tee } from \"./tee.ts\";\n *\n * const gen = async function* gen() {\n * yield 1;\n * yield 2;\n * yield 3;\n * }\n *\n * const [branch1, branch2] = tee(gen());\n *\n * (async () => {\n * for await (const n of branch1) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n *\n * (async () => {\n * for await (const n of branch2) {\n * console.log(n); // => 1, 2, 3\n * }\n * })();\n * ```\n */ export function tee(iterable, n = 2) {\n const queue = new Queue(iterable);\n async function* generator() {\n let buffer = queue.head;\n while(true){\n if (buffer.next) {\n buffer = buffer.next;\n yield buffer.value;\n } else if (queue.done) {\n return;\n } else {\n await queue.next();\n }\n }\n }\n const branches = Array.from({\n length: n\n }).map(()=>generator()\n );\n return branches;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy90ZWUudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJNQWVNLEtBQUs7SUFDVCxDQUFDLE1BQU07SUFDUCxDQUFDLEtBQUs7SUFDTixJQUFJO0lBRUosSUFBSTtnQkFFUSxRQUEwQixDQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsYUFBYTtRQUM1QyxJQUFJLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQztZQUNiLEtBQUssRUFBRSxTQUFTO1lBQ2hCLElBQUksRUFBRSxTQUFTO1FBQ2pCLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLEtBQUs7UUFDdkIsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLO0lBQ25CLENBQUM7VUFFSyxJQUFJLEdBQWtCLENBQUM7UUFDM0IsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUk7UUFDdEMsRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNqQixLQUFLLENBQUMsUUFBUSxHQUFpQixDQUFDO2dCQUM5QixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7Z0JBQ25CLElBQUksRUFBRSxTQUFTO1lBQ2pCLENBQUM7WUFDRCxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLFFBQVE7WUFDM0IsSUFBSSxDQUFDLENBQUMsS0FBSyxHQUFHLFFBQVE7UUFDeEIsQ0FBQyxNQUFNLENBQUM7WUFDTixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUk7UUFDbEIsQ0FBQztJQUNILENBQUM7O0FBR0gsRUE0QkcsQUE1Qkg7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0E0QkcsQUE1QkgsRUE0QkcsQ0FDSCxNQUFNLFVBQVUsR0FBRyxDQUNqQixRQUEwQixFQUMxQixDQUFJLEdBQUcsQ0FBQyxFQUNvQixDQUFDO0lBQzdCLEtBQUssQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBSSxRQUFRO29CQUVuQixTQUFTLEdBQXNCLENBQUM7UUFDOUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSTtjQUNoQixJQUFJLENBQUUsQ0FBQztZQUNaLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2hCLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSTtzQkFDZCxNQUFNLENBQUMsS0FBSztZQUNwQixDQUFDLE1BQU0sRUFBRSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDdEIsTUFBTTtZQUNSLENBQUMsTUFBTSxDQUFDO2dCQUNOLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSTtZQUNsQixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUFDLE1BQU0sRUFBRSxDQUFDO0lBQUMsQ0FBQyxFQUFFLEdBQUcsS0FDdEMsU0FBUzs7SUFLakIsTUFBTSxDQUFDLFFBQVE7QUFDakIsQ0FBQyJ9", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.120.0/async/deadline.ts": { - "Source": { - "source": "import { deferred } from \"./deferred.ts\";\n\nexport class DeadlineError extends Error {\n constructor() {\n super(\"Deadline\");\n this.name = \"DeadlineError\";\n }\n}\n\n/**\n * Create a promise which will be rejected with DeadlineError when a given delay is exceeded.\n */\nexport function deadline(p: Promise, delay: number): Promise {\n const d = deferred();\n const t = setTimeout(() => d.reject(new DeadlineError()), delay);\n return Promise.race([p, d]).finally(() => clearTimeout(t));\n}\n", - "transpiled": "import { deferred } from \"./deferred.ts\";\nexport class DeadlineError extends Error {\n constructor(){\n super(\"Deadline\");\n this.name = \"DeadlineError\";\n }\n}\n/**\n * Create a promise which will be rejected with DeadlineError when a given delay is exceeded.\n */ export function deadline(p, delay) {\n const d = deferred();\n const t = setTimeout(()=>d.reject(new DeadlineError())\n , delay);\n return Promise.race([\n p,\n d\n ]).finally(()=>clearTimeout(t)\n );\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy9kZWFkbGluZS50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxHQUFHLFFBQVEsUUFBUSxDQUFlO0FBRXhDLE1BQU0sT0FBTyxhQUFhLFNBQVMsS0FBSztpQkFDeEIsQ0FBQztRQUNiLEtBQUssQ0FBQyxDQUFVO1FBQ2hCLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBZTtJQUM3QixDQUFDOztBQUdILEVBRUcsQUFGSDs7Q0FFRyxBQUZILEVBRUcsQ0FDSCxNQUFNLFVBQVUsUUFBUSxDQUFJLENBQWEsRUFBRSxLQUFhLEVBQWMsQ0FBQztJQUNyRSxLQUFLLENBQUMsQ0FBQyxHQUFHLFFBQVE7SUFDbEIsS0FBSyxDQUFDLENBQUMsR0FBRyxVQUFVLEtBQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsYUFBYTtNQUFLLEtBQUs7SUFDL0QsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUFBLENBQUM7UUFBRSxDQUFDO0lBQUEsQ0FBQyxFQUFFLE9BQU8sS0FBTyxZQUFZLENBQUMsQ0FBQzs7QUFDMUQsQ0FBQyJ9", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/std@0.120.0/async/deferred.ts"] - } - }, - "https://deno.land/x/fuse@v6.4.1/dist/fuse.esm.js": { - "Source": { - "source": "/**\n * Fuse.js v6.4.1 - Lightweight fuzzy-search (http://fusejs.io)\n *\n * Copyright (c) 2020 Kiro Risk (http://kiro.me)\n * All Rights Reserved. Apache Software License 2.0\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\nfunction isArray(value) {\n return !Array.isArray\n ? getTag(value) === '[object Array]'\n : Array.isArray(value)\n}\n\n// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js\nconst INFINITY = 1 / 0;\nfunction baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value\n }\n let result = value + '';\n return result == '0' && 1 / value == -INFINITY ? '-0' : result\n}\n\nfunction toString(value) {\n return value == null ? '' : baseToString(value)\n}\n\nfunction isString(value) {\n return typeof value === 'string'\n}\n\nfunction isNumber(value) {\n return typeof value === 'number'\n}\n\n// Adapted from: https://github.com/lodash/lodash/blob/master/isBoolean.js\nfunction isBoolean(value) {\n return (\n value === true ||\n value === false ||\n (isObjectLike(value) && getTag(value) == '[object Boolean]')\n )\n}\n\nfunction isObject(value) {\n return typeof value === 'object'\n}\n\n// Checks if `value` is object-like.\nfunction isObjectLike(value) {\n return isObject(value) && value !== null\n}\n\nfunction isDefined(value) {\n return value !== undefined && value !== null\n}\n\nfunction isBlank(value) {\n return !value.trim().length\n}\n\n// Gets the `toStringTag` of `value`.\n// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/getTag.js\nfunction getTag(value) {\n return value == null\n ? value === undefined\n ? '[object Undefined]'\n : '[object Null]'\n : Object.prototype.toString.call(value)\n}\n\nconst EXTENDED_SEARCH_UNAVAILABLE = 'Extended search is not available';\n\nconst INCORRECT_INDEX_TYPE = \"Incorrect 'index' type\";\n\nconst LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = (key) =>\n `Invalid value for key ${key}`;\n\nconst PATTERN_LENGTH_TOO_LARGE = (max) =>\n `Pattern length exceeds max of ${max}.`;\n\nconst MISSING_KEY_PROPERTY = (name) => `Missing ${name} property in key`;\n\nconst INVALID_KEY_WEIGHT_VALUE = (key) =>\n `Property 'weight' in key '${key}' must be a positive integer`;\n\nconst hasOwn = Object.prototype.hasOwnProperty;\n\nclass KeyStore {\n constructor(keys) {\n this._keys = [];\n this._keyMap = {};\n\n let totalWeight = 0;\n\n keys.forEach((key) => {\n let obj = createKey(key);\n\n totalWeight += obj.weight;\n\n this._keys.push(obj);\n this._keyMap[obj.id] = obj;\n\n totalWeight += obj.weight;\n });\n\n // Normalize weights so that their sum is equal to 1\n this._keys.forEach((key) => {\n key.weight /= totalWeight;\n });\n }\n get(keyId) {\n return this._keyMap[keyId]\n }\n keys() {\n return this._keys\n }\n toJSON() {\n return JSON.stringify(this._keys)\n }\n}\n\nfunction createKey(key) {\n let path = null;\n let id = null;\n let src = null;\n let weight = 1;\n\n if (isString(key) || isArray(key)) {\n src = key;\n path = createKeyPath(key);\n id = createKeyId(key);\n } else {\n if (!hasOwn.call(key, 'name')) {\n throw new Error(MISSING_KEY_PROPERTY('name'))\n }\n\n const name = key.name;\n src = name;\n\n if (hasOwn.call(key, 'weight')) {\n weight = key.weight;\n\n if (weight <= 0) {\n throw new Error(INVALID_KEY_WEIGHT_VALUE(name))\n }\n }\n\n path = createKeyPath(name);\n id = createKeyId(name);\n }\n\n return { path, id, weight, src }\n}\n\nfunction createKeyPath(key) {\n return isArray(key) ? key : key.split('.')\n}\n\nfunction createKeyId(key) {\n return isArray(key) ? key.join('.') : key\n}\n\nfunction get(obj, path) {\n let list = [];\n let arr = false;\n\n const deepGet = (obj, path, index) => {\n if (!path[index]) {\n // If there's no path left, we've arrived at the object we care about.\n list.push(obj);\n } else {\n let key = path[index];\n\n const value = obj[key];\n\n if (!isDefined(value)) {\n return\n }\n\n // If we're at the last value in the path, and if it's a string/number/bool,\n // add it to the list\n if (\n index === path.length - 1 &&\n (isString(value) || isNumber(value) || isBoolean(value))\n ) {\n list.push(toString(value));\n } else if (isArray(value)) {\n arr = true;\n // Search each item in the array.\n for (let i = 0, len = value.length; i < len; i += 1) {\n deepGet(value[i], path, index + 1);\n }\n } else if (path.length) {\n // An object. Recurse further.\n deepGet(value, path, index + 1);\n }\n }\n };\n\n // Backwards compatibility (since path used to be a string)\n deepGet(obj, isString(path) ? path.split('.') : path, 0);\n\n return arr ? list : list[0]\n}\n\nconst MatchOptions = {\n // Whether the matches should be included in the result set. When `true`, each record in the result\n // set will include the indices of the matched characters.\n // These can consequently be used for highlighting purposes.\n includeMatches: false,\n // When `true`, the matching function will continue to the end of a search pattern even if\n // a perfect match has already been located in the string.\n findAllMatches: false,\n // Minimum number of characters that must be matched before a result is considered a match\n minMatchCharLength: 1\n};\n\nconst BasicOptions = {\n // When `true`, the algorithm continues searching to the end of the input even if a perfect\n // match is found before the end of the same input.\n isCaseSensitive: false,\n // When true, the matching function will continue to the end of a search pattern even if\n includeScore: false,\n // List of properties that will be searched. This also supports nested properties.\n keys: [],\n // Whether to sort the result list, by score\n shouldSort: true,\n // Default sort function: sort by ascending score, ascending index\n sortFn: (a, b) =>\n a.score === b.score ? (a.idx < b.idx ? -1 : 1) : a.score < b.score ? -1 : 1\n};\n\nconst FuzzyOptions = {\n // Approximately where in the text is the pattern expected to be found?\n location: 0,\n // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match\n // (of both letters and location), a threshold of '1.0' would match anything.\n threshold: 0.6,\n // Determines how close the match must be to the fuzzy location (specified above).\n // An exact letter match which is 'distance' characters away from the fuzzy location\n // would score as a complete mismatch. A distance of '0' requires the match be at\n // the exact location specified, a threshold of '1000' would require a perfect match\n // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold.\n distance: 100\n};\n\nconst AdvancedOptions = {\n // When `true`, it enables the use of unix-like search commands\n useExtendedSearch: false,\n // The get function to use when fetching an object's properties.\n // The default will search nested paths *ie foo.bar.baz*\n getFn: get,\n // When `true`, search will ignore `location` and `distance`, so it won't matter\n // where in the string the pattern appears.\n // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score\n ignoreLocation: false,\n // When `true`, the calculation for the relevance score (used for sorting) will\n // ignore the field-length norm.\n // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm\n ignoreFieldNorm: false\n};\n\nvar Config = {\n ...BasicOptions,\n ...MatchOptions,\n ...FuzzyOptions,\n ...AdvancedOptions\n};\n\nconst SPACE = /[^ ]+/g;\n\n// Field-length norm: the shorter the field, the higher the weight.\n// Set to 3 decimals to reduce index size.\nfunction norm(mantissa = 3) {\n const cache = new Map();\n\n return {\n get(value) {\n const numTokens = value.match(SPACE).length;\n\n if (cache.has(numTokens)) {\n return cache.get(numTokens)\n }\n\n const n = parseFloat((1 / Math.sqrt(numTokens)).toFixed(mantissa));\n\n cache.set(numTokens, n);\n\n return n\n },\n clear() {\n cache.clear();\n }\n }\n}\n\nclass FuseIndex {\n constructor({ getFn = Config.getFn } = {}) {\n this.norm = norm(3);\n this.getFn = getFn;\n this.isCreated = false;\n\n this.setIndexRecords();\n }\n setSources(docs = []) {\n this.docs = docs;\n }\n setIndexRecords(records = []) {\n this.records = records;\n }\n setKeys(keys = []) {\n this.keys = keys;\n this._keysMap = {};\n keys.forEach((key, idx) => {\n this._keysMap[key.id] = idx;\n });\n }\n create() {\n if (this.isCreated || !this.docs.length) {\n return\n }\n\n this.isCreated = true;\n\n // List is Array\n if (isString(this.docs[0])) {\n this.docs.forEach((doc, docIndex) => {\n this._addString(doc, docIndex);\n });\n } else {\n // List is Array\n this.docs.forEach((doc, docIndex) => {\n this._addObject(doc, docIndex);\n });\n }\n\n this.norm.clear();\n }\n // Adds a doc to the end of the index\n add(doc) {\n const idx = this.size();\n\n if (isString(doc)) {\n this._addString(doc, idx);\n } else {\n this._addObject(doc, idx);\n }\n }\n // Removes the doc at the specified index of the index\n removeAt(idx) {\n this.records.splice(idx, 1);\n\n // Change ref index of every subsquent doc\n for (let i = idx, len = this.size(); i < len; i += 1) {\n this.records[i].i -= 1;\n }\n }\n getValueForItemAtKeyId(item, keyId) {\n return item[this._keysMap[keyId]]\n }\n size() {\n return this.records.length\n }\n _addString(doc, docIndex) {\n if (!isDefined(doc) || isBlank(doc)) {\n return\n }\n\n let record = {\n v: doc,\n i: docIndex,\n n: this.norm.get(doc)\n };\n\n this.records.push(record);\n }\n _addObject(doc, docIndex) {\n let record = { i: docIndex, $: {} };\n\n // Iterate over every key (i.e, path), and fetch the value at that key\n this.keys.forEach((key, keyIndex) => {\n // console.log(key)\n let value = this.getFn(doc, key.path);\n\n if (!isDefined(value)) {\n return\n }\n\n if (isArray(value)) {\n let subRecords = [];\n const stack = [{ nestedArrIndex: -1, value }];\n\n while (stack.length) {\n const { nestedArrIndex, value } = stack.pop();\n\n if (!isDefined(value)) {\n continue\n }\n\n if (isString(value) && !isBlank(value)) {\n let subRecord = {\n v: value,\n i: nestedArrIndex,\n n: this.norm.get(value)\n };\n\n subRecords.push(subRecord);\n } else if (isArray(value)) {\n value.forEach((item, k) => {\n stack.push({\n nestedArrIndex: k,\n value: item\n });\n });\n }\n }\n record.$[keyIndex] = subRecords;\n } else if (!isBlank(value)) {\n let subRecord = {\n v: value,\n n: this.norm.get(value)\n };\n\n record.$[keyIndex] = subRecord;\n }\n });\n\n this.records.push(record);\n }\n toJSON() {\n return {\n keys: this.keys,\n records: this.records\n }\n }\n}\n\nfunction createIndex(keys, docs, { getFn = Config.getFn } = {}) {\n const myIndex = new FuseIndex({ getFn });\n myIndex.setKeys(keys.map(createKey));\n myIndex.setSources(docs);\n myIndex.create();\n return myIndex\n}\n\nfunction parseIndex(data, { getFn = Config.getFn } = {}) {\n const { keys, records } = data;\n const myIndex = new FuseIndex({ getFn });\n myIndex.setKeys(keys);\n myIndex.setIndexRecords(records);\n return myIndex\n}\n\nfunction transformMatches(result, data) {\n const matches = result.matches;\n data.matches = [];\n\n if (!isDefined(matches)) {\n return\n }\n\n matches.forEach((match) => {\n if (!isDefined(match.indices) || !match.indices.length) {\n return\n }\n\n const { indices, value } = match;\n\n let obj = {\n indices,\n value\n };\n\n if (match.key) {\n obj.key = match.key.src;\n }\n\n if (match.idx > -1) {\n obj.refIndex = match.idx;\n }\n\n data.matches.push(obj);\n });\n}\n\nfunction transformScore(result, data) {\n data.score = result.score;\n}\n\nfunction computeScore(\n pattern,\n {\n errors = 0,\n currentLocation = 0,\n expectedLocation = 0,\n distance = Config.distance,\n ignoreLocation = Config.ignoreLocation\n } = {}\n) {\n const accuracy = errors / pattern.length;\n\n if (ignoreLocation) {\n return accuracy\n }\n\n const proximity = Math.abs(expectedLocation - currentLocation);\n\n if (!distance) {\n // Dodge divide by zero error.\n return proximity ? 1.0 : accuracy\n }\n\n return accuracy + proximity / distance\n}\n\nfunction convertMaskToIndices(\n matchmask = [],\n minMatchCharLength = Config.minMatchCharLength\n) {\n let indices = [];\n let start = -1;\n let end = -1;\n let i = 0;\n\n for (let len = matchmask.length; i < len; i += 1) {\n let match = matchmask[i];\n if (match && start === -1) {\n start = i;\n } else if (!match && start !== -1) {\n end = i - 1;\n if (end - start + 1 >= minMatchCharLength) {\n indices.push([start, end]);\n }\n start = -1;\n }\n }\n\n // (i-1 - start) + 1 => i - start\n if (matchmask[i - 1] && i - start >= minMatchCharLength) {\n indices.push([start, i - 1]);\n }\n\n return indices\n}\n\n// Machine word size\nconst MAX_BITS = 32;\n\nfunction search(\n text,\n pattern,\n patternAlphabet,\n {\n location = Config.location,\n distance = Config.distance,\n threshold = Config.threshold,\n findAllMatches = Config.findAllMatches,\n minMatchCharLength = Config.minMatchCharLength,\n includeMatches = Config.includeMatches,\n ignoreLocation = Config.ignoreLocation\n } = {}\n) {\n if (pattern.length > MAX_BITS) {\n throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS))\n }\n\n const patternLen = pattern.length;\n // Set starting location at beginning text and initialize the alphabet.\n const textLen = text.length;\n // Handle the case when location > text.length\n const expectedLocation = Math.max(0, Math.min(location, textLen));\n // Highest score beyond which we give up.\n let currentThreshold = threshold;\n // Is there a nearby exact match? (speedup)\n let bestLocation = expectedLocation;\n\n // Performance: only computer matches when the minMatchCharLength > 1\n // OR if `includeMatches` is true.\n const computeMatches = minMatchCharLength > 1 || includeMatches;\n // A mask of the matches, used for building the indices\n const matchMask = computeMatches ? Array(textLen) : [];\n\n let index;\n\n // Get all exact matches, here for speed up\n while ((index = text.indexOf(pattern, bestLocation)) > -1) {\n let score = computeScore(pattern, {\n currentLocation: index,\n expectedLocation,\n distance,\n ignoreLocation\n });\n\n currentThreshold = Math.min(score, currentThreshold);\n bestLocation = index + patternLen;\n\n if (computeMatches) {\n let i = 0;\n while (i < patternLen) {\n matchMask[index + i] = 1;\n i += 1;\n }\n }\n }\n\n // Reset the best location\n bestLocation = -1;\n\n let lastBitArr = [];\n let finalScore = 1;\n let binMax = patternLen + textLen;\n\n const mask = 1 << (patternLen - 1);\n\n for (let i = 0; i < patternLen; i += 1) {\n // Scan for the best match; each iteration allows for one more error.\n // Run a binary search to determine how far from the match location we can stray\n // at this error level.\n let binMin = 0;\n let binMid = binMax;\n\n while (binMin < binMid) {\n const score = computeScore(pattern, {\n errors: i,\n currentLocation: expectedLocation + binMid,\n expectedLocation,\n distance,\n ignoreLocation\n });\n\n if (score <= currentThreshold) {\n binMin = binMid;\n } else {\n binMax = binMid;\n }\n\n binMid = Math.floor((binMax - binMin) / 2 + binMin);\n }\n\n // Use the result from this iteration as the maximum for the next.\n binMax = binMid;\n\n let start = Math.max(1, expectedLocation - binMid + 1);\n let finish = findAllMatches\n ? textLen\n : Math.min(expectedLocation + binMid, textLen) + patternLen;\n\n // Initialize the bit array\n let bitArr = Array(finish + 2);\n\n bitArr[finish + 1] = (1 << i) - 1;\n\n for (let j = finish; j >= start; j -= 1) {\n let currentLocation = j - 1;\n let charMatch = patternAlphabet[text.charAt(currentLocation)];\n\n if (computeMatches) {\n // Speed up: quick bool to int conversion (i.e, `charMatch ? 1 : 0`)\n matchMask[currentLocation] = +!!charMatch;\n }\n\n // First pass: exact match\n bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch;\n\n // Subsequent passes: fuzzy match\n if (i) {\n bitArr[j] |=\n ((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1 | lastBitArr[j + 1];\n }\n\n if (bitArr[j] & mask) {\n finalScore = computeScore(pattern, {\n errors: i,\n currentLocation,\n expectedLocation,\n distance,\n ignoreLocation\n });\n\n // This match will almost certainly be better than any existing match.\n // But check anyway.\n if (finalScore <= currentThreshold) {\n // Indeed it is\n currentThreshold = finalScore;\n bestLocation = currentLocation;\n\n // Already passed `loc`, downhill from here on in.\n if (bestLocation <= expectedLocation) {\n break\n }\n\n // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`.\n start = Math.max(1, 2 * expectedLocation - bestLocation);\n }\n }\n }\n\n // No hope for a (better) match at greater error levels.\n const score = computeScore(pattern, {\n errors: i + 1,\n currentLocation: expectedLocation,\n expectedLocation,\n distance,\n ignoreLocation\n });\n\n if (score > currentThreshold) {\n break\n }\n\n lastBitArr = bitArr;\n }\n\n const result = {\n isMatch: bestLocation >= 0,\n // Count exact matches (those with a score of 0) to be \"almost\" exact\n score: Math.max(0.001, finalScore)\n };\n\n if (computeMatches) {\n const indices = convertMaskToIndices(matchMask, minMatchCharLength);\n if (!indices.length) {\n result.isMatch = false;\n } else if (includeMatches) {\n result.indices = indices;\n }\n }\n\n return result\n}\n\nfunction createPatternAlphabet(pattern) {\n let mask = {};\n\n for (let i = 0, len = pattern.length; i < len; i += 1) {\n const char = pattern.charAt(i);\n mask[char] = (mask[char] || 0) | (1 << (len - i - 1));\n }\n\n return mask\n}\n\nclass BitapSearch {\n constructor(\n pattern,\n {\n location = Config.location,\n threshold = Config.threshold,\n distance = Config.distance,\n includeMatches = Config.includeMatches,\n findAllMatches = Config.findAllMatches,\n minMatchCharLength = Config.minMatchCharLength,\n isCaseSensitive = Config.isCaseSensitive,\n ignoreLocation = Config.ignoreLocation\n } = {}\n ) {\n this.options = {\n location,\n threshold,\n distance,\n includeMatches,\n findAllMatches,\n minMatchCharLength,\n isCaseSensitive,\n ignoreLocation\n };\n\n this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase();\n\n this.chunks = [];\n\n if (!this.pattern.length) {\n return\n }\n\n const addChunk = (pattern, startIndex) => {\n this.chunks.push({\n pattern,\n alphabet: createPatternAlphabet(pattern),\n startIndex\n });\n };\n\n const len = this.pattern.length;\n\n if (len > MAX_BITS) {\n let i = 0;\n const remainder = len % MAX_BITS;\n const end = len - remainder;\n\n while (i < end) {\n addChunk(this.pattern.substr(i, MAX_BITS), i);\n i += MAX_BITS;\n }\n\n if (remainder) {\n const startIndex = len - MAX_BITS;\n addChunk(this.pattern.substr(startIndex), startIndex);\n }\n } else {\n addChunk(this.pattern, 0);\n }\n }\n\n searchIn(text) {\n const { isCaseSensitive, includeMatches } = this.options;\n\n if (!isCaseSensitive) {\n text = text.toLowerCase();\n }\n\n // Exact match\n if (this.pattern === text) {\n let result = {\n isMatch: true,\n score: 0\n };\n\n if (includeMatches) {\n result.indices = [[0, text.length - 1]];\n }\n\n return result\n }\n\n // Otherwise, use Bitap algorithm\n const {\n location,\n distance,\n threshold,\n findAllMatches,\n minMatchCharLength,\n ignoreLocation\n } = this.options;\n\n let allIndices = [];\n let totalScore = 0;\n let hasMatches = false;\n\n this.chunks.forEach(({ pattern, alphabet, startIndex }) => {\n const { isMatch, score, indices } = search(text, pattern, alphabet, {\n location: location + startIndex,\n distance,\n threshold,\n findAllMatches,\n minMatchCharLength,\n includeMatches,\n ignoreLocation\n });\n\n if (isMatch) {\n hasMatches = true;\n }\n\n totalScore += score;\n\n if (isMatch && indices) {\n allIndices = [...allIndices, ...indices];\n }\n });\n\n let result = {\n isMatch: hasMatches,\n score: hasMatches ? totalScore / this.chunks.length : 1\n };\n\n if (hasMatches && includeMatches) {\n result.indices = allIndices;\n }\n\n return result\n }\n}\n\nclass BaseMatch {\n constructor(pattern) {\n this.pattern = pattern;\n }\n static isMultiMatch(pattern) {\n return getMatch(pattern, this.multiRegex)\n }\n static isSingleMatch(pattern) {\n return getMatch(pattern, this.singleRegex)\n }\n search(/*text*/) {}\n}\n\nfunction getMatch(pattern, exp) {\n const matches = pattern.match(exp);\n return matches ? matches[1] : null\n}\n\n// Token: 'file\n\nclass ExactMatch extends BaseMatch {\n constructor(pattern) {\n super(pattern);\n }\n static get type() {\n return 'exact'\n }\n static get multiRegex() {\n return /^=\"(.*)\"$/\n }\n static get singleRegex() {\n return /^=(.*)$/\n }\n search(text) {\n const isMatch = text === this.pattern;\n\n return {\n isMatch,\n score: isMatch ? 0 : 1,\n indices: [0, this.pattern.length - 1]\n }\n }\n}\n\n// Token: !fire\n\nclass InverseExactMatch extends BaseMatch {\n constructor(pattern) {\n super(pattern);\n }\n static get type() {\n return 'inverse-exact'\n }\n static get multiRegex() {\n return /^!\"(.*)\"$/\n }\n static get singleRegex() {\n return /^!(.*)$/\n }\n search(text) {\n const index = text.indexOf(this.pattern);\n const isMatch = index === -1;\n\n return {\n isMatch,\n score: isMatch ? 0 : 1,\n indices: [0, text.length - 1]\n }\n }\n}\n\n// Token: ^file\n\nclass PrefixExactMatch extends BaseMatch {\n constructor(pattern) {\n super(pattern);\n }\n static get type() {\n return 'prefix-exact'\n }\n static get multiRegex() {\n return /^\\^\"(.*)\"$/\n }\n static get singleRegex() {\n return /^\\^(.*)$/\n }\n search(text) {\n const isMatch = text.startsWith(this.pattern);\n\n return {\n isMatch,\n score: isMatch ? 0 : 1,\n indices: [0, this.pattern.length - 1]\n }\n }\n}\n\n// Token: !^fire\n\nclass InversePrefixExactMatch extends BaseMatch {\n constructor(pattern) {\n super(pattern);\n }\n static get type() {\n return 'inverse-prefix-exact'\n }\n static get multiRegex() {\n return /^!\\^\"(.*)\"$/\n }\n static get singleRegex() {\n return /^!\\^(.*)$/\n }\n search(text) {\n const isMatch = !text.startsWith(this.pattern);\n\n return {\n isMatch,\n score: isMatch ? 0 : 1,\n indices: [0, text.length - 1]\n }\n }\n}\n\n// Token: .file$\n\nclass SuffixExactMatch extends BaseMatch {\n constructor(pattern) {\n super(pattern);\n }\n static get type() {\n return 'suffix-exact'\n }\n static get multiRegex() {\n return /^\"(.*)\"\\$$/\n }\n static get singleRegex() {\n return /^(.*)\\$$/\n }\n search(text) {\n const isMatch = text.endsWith(this.pattern);\n\n return {\n isMatch,\n score: isMatch ? 0 : 1,\n indices: [text.length - this.pattern.length, text.length - 1]\n }\n }\n}\n\n// Token: !.file$\n\nclass InverseSuffixExactMatch extends BaseMatch {\n constructor(pattern) {\n super(pattern);\n }\n static get type() {\n return 'inverse-suffix-exact'\n }\n static get multiRegex() {\n return /^!\"(.*)\"\\$$/\n }\n static get singleRegex() {\n return /^!(.*)\\$$/\n }\n search(text) {\n const isMatch = !text.endsWith(this.pattern);\n return {\n isMatch,\n score: isMatch ? 0 : 1,\n indices: [0, text.length - 1]\n }\n }\n}\n\nclass FuzzyMatch extends BaseMatch {\n constructor(\n pattern,\n {\n location = Config.location,\n threshold = Config.threshold,\n distance = Config.distance,\n includeMatches = Config.includeMatches,\n findAllMatches = Config.findAllMatches,\n minMatchCharLength = Config.minMatchCharLength,\n isCaseSensitive = Config.isCaseSensitive\n } = {}\n ) {\n super(pattern);\n this._bitapSearch = new BitapSearch(pattern, {\n location,\n threshold,\n distance,\n includeMatches,\n findAllMatches,\n minMatchCharLength,\n isCaseSensitive\n });\n }\n static get type() {\n return 'fuzzy'\n }\n static get multiRegex() {\n return /^\"(.*)\"$/\n }\n static get singleRegex() {\n return /^(.*)$/\n }\n search(text) {\n return this._bitapSearch.searchIn(text)\n }\n}\n\n// Token: 'file\n\nclass IncludeMatch extends BaseMatch {\n constructor(pattern) {\n super(pattern);\n }\n static get type() {\n return 'include'\n }\n static get multiRegex() {\n return /^'\"(.*)\"$/\n }\n static get singleRegex() {\n return /^'(.*)$/\n }\n search(text) {\n let location = 0;\n let index;\n\n const indices = [];\n const patternLen = this.pattern.length;\n\n // Get all exact matches\n while ((index = text.indexOf(this.pattern, location)) > -1) {\n location = index + patternLen;\n indices.push([index, location - 1]);\n }\n\n const isMatch = !!indices.length;\n\n return {\n isMatch,\n score: isMatch ? 1 : 0,\n indices\n }\n }\n}\n\n// ❗Order is important. DO NOT CHANGE.\nconst searchers = [\n ExactMatch,\n IncludeMatch,\n PrefixExactMatch,\n InversePrefixExactMatch,\n InverseSuffixExactMatch,\n SuffixExactMatch,\n InverseExactMatch,\n FuzzyMatch\n];\n\nconst searchersLen = searchers.length;\n\n// Regex to split by spaces, but keep anything in quotes together\nconst SPACE_RE = / +(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)/;\nconst OR_TOKEN = '|';\n\n// Return a 2D array representation of the query, for simpler parsing.\n// Example:\n// \"^core go$ | rb$ | py$ xy$\" => [[\"^core\", \"go$\"], [\"rb$\"], [\"py$\", \"xy$\"]]\nfunction parseQuery(pattern, options = {}) {\n return pattern.split(OR_TOKEN).map((item) => {\n let query = item\n .trim()\n .split(SPACE_RE)\n .filter((item) => item && !!item.trim());\n\n let results = [];\n for (let i = 0, len = query.length; i < len; i += 1) {\n const queryItem = query[i];\n\n // 1. Handle multiple query match (i.e, once that are quoted, like `\"hello world\"`)\n let found = false;\n let idx = -1;\n while (!found && ++idx < searchersLen) {\n const searcher = searchers[idx];\n let token = searcher.isMultiMatch(queryItem);\n if (token) {\n results.push(new searcher(token, options));\n found = true;\n }\n }\n\n if (found) {\n continue\n }\n\n // 2. Handle single query matches (i.e, once that are *not* quoted)\n idx = -1;\n while (++idx < searchersLen) {\n const searcher = searchers[idx];\n let token = searcher.isSingleMatch(queryItem);\n if (token) {\n results.push(new searcher(token, options));\n break\n }\n }\n }\n\n return results\n })\n}\n\n// These extended matchers can return an array of matches, as opposed\n// to a singl match\nconst MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]);\n\n/**\n * Command-like searching\n * ======================\n *\n * Given multiple search terms delimited by spaces.e.g. `^jscript .python$ ruby !java`,\n * search in a given text.\n *\n * Search syntax:\n *\n * | Token | Match type | Description |\n * | ----------- | -------------------------- | -------------------------------------- |\n * | `jscript` | fuzzy-match | Items that fuzzy match `jscript` |\n * | `=scheme` | exact-match | Items that are `scheme` |\n * | `'python` | include-match | Items that include `python` |\n * | `!ruby` | inverse-exact-match | Items that do not include `ruby` |\n * | `^java` | prefix-exact-match | Items that start with `java` |\n * | `!^earlang` | inverse-prefix-exact-match | Items that do not start with `earlang` |\n * | `.js$` | suffix-exact-match | Items that end with `.js` |\n * | `!.go$` | inverse-suffix-exact-match | Items that do not end with `.go` |\n *\n * A single pipe character acts as an OR operator. For example, the following\n * query matches entries that start with `core` and end with either`go`, `rb`,\n * or`py`.\n *\n * ```\n * ^core go$ | rb$ | py$\n * ```\n */\nclass ExtendedSearch {\n constructor(\n pattern,\n {\n isCaseSensitive = Config.isCaseSensitive,\n includeMatches = Config.includeMatches,\n minMatchCharLength = Config.minMatchCharLength,\n findAllMatches = Config.findAllMatches,\n location = Config.location,\n threshold = Config.threshold,\n distance = Config.distance\n } = {}\n ) {\n this.query = null;\n this.options = {\n isCaseSensitive,\n includeMatches,\n minMatchCharLength,\n findAllMatches,\n location,\n threshold,\n distance\n };\n\n this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase();\n this.query = parseQuery(this.pattern, this.options);\n }\n\n static condition(_, options) {\n return options.useExtendedSearch\n }\n\n searchIn(text) {\n const query = this.query;\n\n if (!query) {\n return {\n isMatch: false,\n score: 1\n }\n }\n\n const { includeMatches, isCaseSensitive } = this.options;\n\n text = isCaseSensitive ? text : text.toLowerCase();\n\n let numMatches = 0;\n let allIndices = [];\n let totalScore = 0;\n\n // ORs\n for (let i = 0, qLen = query.length; i < qLen; i += 1) {\n const searchers = query[i];\n\n // Reset indices\n allIndices.length = 0;\n numMatches = 0;\n\n // ANDs\n for (let j = 0, pLen = searchers.length; j < pLen; j += 1) {\n const searcher = searchers[j];\n const { isMatch, indices, score } = searcher.search(text);\n\n if (isMatch) {\n numMatches += 1;\n totalScore += score;\n if (includeMatches) {\n const type = searcher.constructor.type;\n if (MultiMatchSet.has(type)) {\n allIndices = [...allIndices, ...indices];\n } else {\n allIndices.push(indices);\n }\n }\n } else {\n totalScore = 0;\n numMatches = 0;\n allIndices.length = 0;\n break\n }\n }\n\n // OR condition, so if TRUE, return\n if (numMatches) {\n let result = {\n isMatch: true,\n score: totalScore / numMatches\n };\n\n if (includeMatches) {\n result.indices = allIndices;\n }\n\n return result\n }\n }\n\n // Nothing was matched\n return {\n isMatch: false,\n score: 1\n }\n }\n}\n\nconst registeredSearchers = [];\n\nfunction register(...args) {\n registeredSearchers.push(...args);\n}\n\nfunction createSearcher(pattern, options) {\n for (let i = 0, len = registeredSearchers.length; i < len; i += 1) {\n let searcherClass = registeredSearchers[i];\n if (searcherClass.condition(pattern, options)) {\n return new searcherClass(pattern, options)\n }\n }\n\n return new BitapSearch(pattern, options)\n}\n\nconst LogicalOperator = {\n AND: '$and',\n OR: '$or'\n};\n\nconst KeyType = {\n PATH: '$path',\n PATTERN: '$val'\n};\n\nconst isExpression = (query) =>\n !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]);\n\nconst isPath = (query) => !!query[KeyType.PATH];\n\nconst isLeaf = (query) =>\n !isArray(query) && isObject(query) && !isExpression(query);\n\nconst convertToExplicit = (query) => ({\n [LogicalOperator.AND]: Object.keys(query).map((key) => ({\n [key]: query[key]\n }))\n});\n\n// When `auto` is `true`, the parse function will infer and initialize and add\n// the appropriate `Searcher` instance\nfunction parse(query, options, { auto = true } = {}) {\n const next = (query) => {\n let keys = Object.keys(query);\n\n const isQueryPath = isPath(query);\n\n if (!isQueryPath && keys.length > 1 && !isExpression(query)) {\n return next(convertToExplicit(query))\n }\n\n if (isLeaf(query)) {\n const key = isQueryPath ? query[KeyType.PATH] : keys[0];\n\n const pattern = isQueryPath ? query[KeyType.PATTERN] : query[key];\n\n if (!isString(pattern)) {\n throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key))\n }\n\n const obj = {\n keyId: createKeyId(key),\n pattern\n };\n\n if (auto) {\n obj.searcher = createSearcher(pattern, options);\n }\n\n return obj\n }\n\n let node = {\n children: [],\n operator: keys[0]\n };\n\n keys.forEach((key) => {\n const value = query[key];\n\n if (isArray(value)) {\n value.forEach((item) => {\n node.children.push(next(item));\n });\n }\n });\n\n return node\n };\n\n if (!isExpression(query)) {\n query = convertToExplicit(query);\n }\n\n return next(query)\n}\n\nclass Fuse {\n constructor(docs, options = {}, index) {\n this.options = { ...Config, ...options };\n\n if (\n this.options.useExtendedSearch &&\n !true\n ) {\n throw new Error(EXTENDED_SEARCH_UNAVAILABLE)\n }\n\n this._keyStore = new KeyStore(this.options.keys);\n\n this.setCollection(docs, index);\n }\n\n setCollection(docs, index) {\n this._docs = docs;\n\n if (index && !(index instanceof FuseIndex)) {\n throw new Error(INCORRECT_INDEX_TYPE)\n }\n\n this._myIndex =\n index ||\n createIndex(this.options.keys, this._docs, {\n getFn: this.options.getFn\n });\n }\n\n add(doc) {\n if (!isDefined(doc)) {\n return\n }\n\n this._docs.push(doc);\n this._myIndex.add(doc);\n }\n\n remove(predicate = (/* doc, idx */) => false) {\n const results = [];\n\n for (let i = 0, len = this._docs.length; i < len; i += 1) {\n const doc = this._docs[i];\n if (predicate(doc, i)) {\n this.removeAt(i);\n i -= 1;\n\n results.push(doc);\n }\n }\n\n return results\n }\n\n removeAt(idx) {\n this._docs.splice(idx, 1);\n this._myIndex.removeAt(idx);\n }\n\n getIndex() {\n return this._myIndex\n }\n\n search(query, { limit = -1 } = {}) {\n const {\n includeMatches,\n includeScore,\n shouldSort,\n sortFn,\n ignoreFieldNorm\n } = this.options;\n\n let results = isString(query)\n ? isString(this._docs[0])\n ? this._searchStringList(query)\n : this._searchObjectList(query)\n : this._searchLogical(query);\n\n computeScore$1(results, { ignoreFieldNorm });\n\n if (shouldSort) {\n results.sort(sortFn);\n }\n\n if (isNumber(limit) && limit > -1) {\n results = results.slice(0, limit);\n }\n\n return format(results, this._docs, {\n includeMatches,\n includeScore\n })\n }\n\n _searchStringList(query) {\n const searcher = createSearcher(query, this.options);\n const { records } = this._myIndex;\n const results = [];\n\n // Iterate over every string in the index\n records.forEach(({ v: text, i: idx, n: norm }) => {\n if (!isDefined(text)) {\n return\n }\n\n const { isMatch, score, indices } = searcher.searchIn(text);\n\n if (isMatch) {\n results.push({\n item: text,\n idx,\n matches: [{ score, value: text, norm, indices }]\n });\n }\n });\n\n return results\n }\n\n _searchLogical(query) {\n\n const expression = parse(query, this.options);\n\n const evaluate = (node, item, idx) => {\n if (!node.children) {\n const { keyId, searcher } = node;\n\n const matches = this._findMatches({\n key: this._keyStore.get(keyId),\n value: this._myIndex.getValueForItemAtKeyId(item, keyId),\n searcher\n });\n\n if (matches && matches.length) {\n return [\n {\n idx,\n item,\n matches\n }\n ]\n }\n\n return []\n }\n\n /*eslint indent: [2, 2, {\"SwitchCase\": 1}]*/\n switch (node.operator) {\n case LogicalOperator.AND: {\n const res = [];\n for (let i = 0, len = node.children.length; i < len; i += 1) {\n const child = node.children[i];\n const result = evaluate(child, item, idx);\n if (result.length) {\n res.push(...result);\n } else {\n return []\n }\n }\n return res\n }\n case LogicalOperator.OR: {\n const res = [];\n for (let i = 0, len = node.children.length; i < len; i += 1) {\n const child = node.children[i];\n const result = evaluate(child, item, idx);\n if (result.length) {\n res.push(...result);\n break\n }\n }\n return res\n }\n }\n };\n\n const records = this._myIndex.records;\n const resultMap = {};\n const results = [];\n\n records.forEach(({ $: item, i: idx }) => {\n if (isDefined(item)) {\n let expResults = evaluate(expression, item, idx);\n\n if (expResults.length) {\n // Dedupe when adding\n if (!resultMap[idx]) {\n resultMap[idx] = { idx, item, matches: [] };\n results.push(resultMap[idx]);\n }\n expResults.forEach(({ matches }) => {\n resultMap[idx].matches.push(...matches);\n });\n }\n }\n });\n\n return results\n }\n\n _searchObjectList(query) {\n const searcher = createSearcher(query, this.options);\n const { keys, records } = this._myIndex;\n const results = [];\n\n // List is Array\n records.forEach(({ $: item, i: idx }) => {\n if (!isDefined(item)) {\n return\n }\n\n let matches = [];\n\n // Iterate over every key (i.e, path), and fetch the value at that key\n keys.forEach((key, keyIndex) => {\n matches.push(\n ...this._findMatches({\n key,\n value: item[keyIndex],\n searcher\n })\n );\n });\n\n if (matches.length) {\n results.push({\n idx,\n item,\n matches\n });\n }\n });\n\n return results\n }\n _findMatches({ key, value, searcher }) {\n if (!isDefined(value)) {\n return []\n }\n\n let matches = [];\n\n if (isArray(value)) {\n value.forEach(({ v: text, i: idx, n: norm }) => {\n if (!isDefined(text)) {\n return\n }\n\n const { isMatch, score, indices } = searcher.searchIn(text);\n\n if (isMatch) {\n matches.push({\n score,\n key,\n value: text,\n idx,\n norm,\n indices\n });\n }\n });\n } else {\n const { v: text, n: norm } = value;\n\n const { isMatch, score, indices } = searcher.searchIn(text);\n\n if (isMatch) {\n matches.push({ score, key, value: text, norm, indices });\n }\n }\n\n return matches\n }\n}\n\n// Practical scoring function\nfunction computeScore$1(results, { ignoreFieldNorm = Config.ignoreFieldNorm }) {\n results.forEach((result) => {\n let totalScore = 1;\n\n result.matches.forEach(({ key, norm, score }) => {\n const weight = key ? key.weight : null;\n\n totalScore *= Math.pow(\n score === 0 && weight ? Number.EPSILON : score,\n (weight || 1) * (ignoreFieldNorm ? 1 : norm)\n );\n });\n\n result.score = totalScore;\n });\n}\n\nfunction format(\n results,\n docs,\n {\n includeMatches = Config.includeMatches,\n includeScore = Config.includeScore\n } = {}\n) {\n const transformers = [];\n\n if (includeMatches) transformers.push(transformMatches);\n if (includeScore) transformers.push(transformScore);\n\n return results.map((result) => {\n const { idx } = result;\n\n const data = {\n item: docs[idx],\n refIndex: idx\n };\n\n if (transformers.length) {\n transformers.forEach((transformer) => {\n transformer(result, data);\n });\n }\n\n return data\n })\n}\n\nFuse.version = '6.4.1';\nFuse.createIndex = createIndex;\nFuse.parseIndex = parseIndex;\nFuse.config = Config;\n\n{\n Fuse.parseQuery = parse;\n}\n\n{\n register(ExtendedSearch);\n}\n\nexport default Fuse;\n", - "transpiled": null, - "content_type": "application/javascript", - "deps": [] - } - }, - "https://deno.land/std@0.108.0/async/mux_async_iterator.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nimport { Deferred, deferred } from \"./deferred.ts\";\n\ninterface TaggedYieldedValue {\n iterator: AsyncIterator;\n value: T;\n}\n\n/** The MuxAsyncIterator class multiplexes multiple async iterators into a\n * single stream. It currently makes an assumption:\n * - The final result (the value returned and not yielded from the iterator)\n * does not matter; if there is any, it is discarded.\n */\nexport class MuxAsyncIterator implements AsyncIterable {\n private iteratorCount = 0;\n private yields: Array> = [];\n // deno-lint-ignore no-explicit-any\n private throws: any[] = [];\n private signal: Deferred = deferred();\n\n add(iterable: AsyncIterable): void {\n ++this.iteratorCount;\n this.callIteratorNext(iterable[Symbol.asyncIterator]());\n }\n\n private async callIteratorNext(\n iterator: AsyncIterator,\n ) {\n try {\n const { value, done } = await iterator.next();\n if (done) {\n --this.iteratorCount;\n } else {\n this.yields.push({ iterator, value });\n }\n } catch (e) {\n this.throws.push(e);\n }\n this.signal.resolve();\n }\n\n async *iterate(): AsyncIterableIterator {\n while (this.iteratorCount > 0) {\n // Sleep until any of the wrapped iterators yields.\n await this.signal;\n\n // Note that while we're looping over `yields`, new items may be added.\n for (let i = 0; i < this.yields.length; i++) {\n const { iterator, value } = this.yields[i];\n yield value;\n this.callIteratorNext(iterator);\n }\n\n if (this.throws.length) {\n for (const e of this.throws) {\n throw e;\n }\n this.throws.length = 0;\n }\n // Clear the `yields` list and reset the `signal` promise.\n this.yields.length = 0;\n this.signal = deferred();\n }\n }\n\n [Symbol.asyncIterator](): AsyncIterator {\n return this.iterate();\n }\n}\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nimport { deferred } from \"./deferred.ts\";\n/** The MuxAsyncIterator class multiplexes multiple async iterators into a\n * single stream. It currently makes an assumption:\n * - The final result (the value returned and not yielded from the iterator)\n * does not matter; if there is any, it is discarded.\n */ export class MuxAsyncIterator {\n iteratorCount = 0;\n yields = [];\n // deno-lint-ignore no-explicit-any\n throws = [];\n signal = deferred();\n add(iterable) {\n ++this.iteratorCount;\n this.callIteratorNext(iterable[Symbol.asyncIterator]());\n }\n async callIteratorNext(iterator) {\n try {\n const { value , done } = await iterator.next();\n if (done) {\n --this.iteratorCount;\n } else {\n this.yields.push({\n iterator,\n value\n });\n }\n } catch (e) {\n this.throws.push(e);\n }\n this.signal.resolve();\n }\n async *iterate() {\n while(this.iteratorCount > 0){\n // Sleep until any of the wrapped iterators yields.\n await this.signal;\n // Note that while we're looping over `yields`, new items may be added.\n for(let i = 0; i < this.yields.length; i++){\n const { iterator , value } = this.yields[i];\n yield value;\n this.callIteratorNext(iterator);\n }\n if (this.throws.length) {\n for (const e of this.throws){\n throw e;\n }\n this.throws.length = 0;\n }\n // Clear the `yields` list and reset the `signal` promise.\n this.yields.length = 0;\n this.signal = deferred();\n }\n }\n [Symbol.asyncIterator]() {\n return this.iterate();\n }\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy9tdXhfYXN5bmNfaXRlcmF0b3IudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEVBQTBFLEFBQTFFLHdFQUEwRTtBQUMxRSxNQUFNLEdBQWEsUUFBUSxRQUFRLENBQWU7QUFPbEQsRUFJRyxBQUpIOzs7O0NBSUcsQUFKSCxFQUlHLENBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQUNuQixhQUFhLEdBQUcsQ0FBQztJQUNqQixNQUFNLEdBQWlDLENBQUMsQ0FBQztJQUNqRCxFQUFtQyxBQUFuQyxpQ0FBbUM7SUFDM0IsTUFBTSxHQUFVLENBQUMsQ0FBQztJQUNsQixNQUFNLEdBQW1CLFFBQVE7SUFFekMsR0FBRyxDQUFDLFFBQTBCLEVBQVEsQ0FBQztVQUNuQyxJQUFJLENBQUMsYUFBYTtRQUNwQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxhQUFhO0lBQ3JELENBQUM7VUFFYSxnQkFBZ0IsQ0FDNUIsUUFBMEIsRUFDMUIsQ0FBQztRQUNELEdBQUcsQ0FBQyxDQUFDO1lBQ0gsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUUsSUFBSSxFQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUk7WUFDM0MsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDO2tCQUNQLElBQUksQ0FBQyxhQUFhO1lBQ3RCLENBQUMsTUFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQUMsUUFBUTtvQkFBRSxLQUFLO2dCQUFDLENBQUM7WUFDdEMsQ0FBQztRQUNILENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BCLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU87SUFDckIsQ0FBQztXQUVNLE9BQU8sR0FBNkIsQ0FBQztjQUNuQyxJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBRSxDQUFDO1lBQzlCLEVBQW1ELEFBQW5ELGlEQUFtRDtZQUNuRCxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU07WUFFakIsRUFBdUUsQUFBdkUscUVBQXVFO1lBQ3ZFLEdBQUcsQ0FBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFJLENBQUM7Z0JBQzVDLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxHQUFFLEtBQUssRUFBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO3NCQUNuQyxLQUFLO2dCQUNYLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRO1lBQ2hDLENBQUM7WUFFRCxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDdkIsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBRSxDQUFDO29CQUM1QixLQUFLLENBQUMsQ0FBQztnQkFDVCxDQUFDO2dCQUNELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUM7WUFDeEIsQ0FBQztZQUNELEVBQTBELEFBQTFELHdEQUEwRDtZQUMxRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDO1lBQ3RCLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUTtRQUN4QixDQUFDO0lBQ0gsQ0FBQztLQUVBLE1BQU0sQ0FBQyxhQUFhLElBQXNCLENBQUM7UUFDMUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPO0lBQ3JCLENBQUMifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/std@0.108.0/async/deferred.ts"] - } - }, - "https://deno.land/x/pretty_bytes@v1.0.5/mod.ts": { - "Source": { - "source": "// Copyright 2014-2021 Sindre Sorhus. All rights reserved. MIT license.\n// Copyright 2021 Yoshiya Hinosawa. All rights reserved. MIT license.\n\ntype LocaleOptions = {\n minimumFractionDigits?: number;\n maximumFractionDigits?: number;\n};\n\n/**\n * The options for pretty printing the byte numbers.\n */\nexport interface PrettyBytesOptions {\n /** Uses bits representation. Default is false. */\n bits?: boolean;\n /** Uses binary bytes (e.g. kibibyte). Default is false. */\n binary?: boolean;\n /** Include plus sign for positive numbers. */\n signed?: boolean;\n /** Uses localized number formatting. If it is set to true, uses default locale on the system. If it's set to string, uses that locale. The given string should be BCP 47 language tag (ref: https://en.wikipedia.org/wiki/IETF_language_tag). You can also give the list of language tags. */\n locale?: boolean | string | string[];\n /** The minimum number of fraction digits to display. If neither minimumFractionDigits or maximumFractionDigits are set, the default behavior is to round to 3 significant digits. */\n minimumFractionDigits?: number;\n /** The maximum number of fraction digits to display. If neither minimumFractionDigits or maximumFractionDigits are set, the default behavior is to round to 3 significant digits. */\n maximumFractionDigits?: number;\n}\n\n/**\n * Convert bytes to a human readable string: 1337 → 1.34 kB\n *\n * @param num The number to format\n * @param options The options\n */\nexport function prettyBytes(\n num: number,\n options: PrettyBytesOptions = {},\n): string {\n if (!Number.isFinite(num)) {\n throw new TypeError(`Expected a finite number, got ${typeof num}: ${num}`);\n }\n\n const UNITS_FIRSTLETTER = (options.bits ? \"b\" : \"B\") + \"kMGTPEZY\";\n\n if (options.signed && num === 0) {\n return ` 0 ${UNITS_FIRSTLETTER[0]}`;\n }\n\n const prefix = num < 0 ? \"-\" : (options.signed ? \"+\" : \"\");\n num = Math.abs(num);\n\n const localeOptions = getLocaleOptions(options);\n\n if (num < 1) {\n const numberString = toLocaleString(num, options.locale, localeOptions);\n return prefix + numberString + \" \" + UNITS_FIRSTLETTER[0];\n }\n\n const exponent = Math.min(\n Math.floor(\n options.binary ? Math.log(num) / Math.log(1024) : Math.log10(num) / 3,\n ),\n UNITS_FIRSTLETTER.length - 1,\n );\n num /= Math.pow(options.binary ? 1024 : 1000, exponent);\n\n if (!localeOptions) {\n num = Number(num.toPrecision(3));\n }\n\n const numberString = toLocaleString(\n num,\n options.locale,\n localeOptions,\n );\n\n let unit = UNITS_FIRSTLETTER[exponent];\n if (exponent > 0) {\n unit += options.binary ? \"i\" : \"\";\n unit += options.bits ? \"bit\" : \"B\";\n }\n\n return prefix + numberString + \" \" + unit;\n}\n\nfunction getLocaleOptions(\n { maximumFractionDigits, minimumFractionDigits }: PrettyBytesOptions,\n): LocaleOptions | undefined {\n if (maximumFractionDigits || minimumFractionDigits) {\n return {\n maximumFractionDigits,\n minimumFractionDigits,\n };\n }\n}\n\n/**\n * Formats the given number using `Number#toLocaleString`.\n * - If locale is a string, the value is expected to be a locale-key (for example: `de`).\n * - If locale is true, the system default locale is used for translation.\n * - If no value for locale is specified, the number is returned unmodified.\n */\nfunction toLocaleString(\n num: number,\n locale: boolean | string | string[] | undefined,\n options: LocaleOptions | undefined,\n): string {\n if (typeof locale === \"string\" || Array.isArray(locale)) {\n return num.toLocaleString(locale, options);\n } else if (locale === true || options !== undefined) {\n return num.toLocaleString(undefined, options);\n }\n\n return num.toString();\n}\n", - "transpiled": "/**\n * Convert bytes to a human readable string: 1337 → 1.34 kB\n *\n * @param num The number to format\n * @param options The options\n */ export function prettyBytes(num, options = {\n}) {\n if (!Number.isFinite(num)) {\n throw new TypeError(`Expected a finite number, got ${typeof num}: ${num}`);\n }\n const UNITS_FIRSTLETTER = (options.bits ? \"b\" : \"B\") + \"kMGTPEZY\";\n if (options.signed && num === 0) {\n return ` 0 ${UNITS_FIRSTLETTER[0]}`;\n }\n const prefix = num < 0 ? \"-\" : options.signed ? \"+\" : \"\";\n num = Math.abs(num);\n const localeOptions = getLocaleOptions(options);\n if (num < 1) {\n const numberString = toLocaleString(num, options.locale, localeOptions);\n return prefix + numberString + \" \" + UNITS_FIRSTLETTER[0];\n }\n const exponent = Math.min(Math.floor(options.binary ? Math.log(num) / Math.log(1024) : Math.log10(num) / 3), UNITS_FIRSTLETTER.length - 1);\n num /= Math.pow(options.binary ? 1024 : 1000, exponent);\n if (!localeOptions) {\n num = Number(num.toPrecision(3));\n }\n const numberString = toLocaleString(num, options.locale, localeOptions);\n let unit = UNITS_FIRSTLETTER[exponent];\n if (exponent > 0) {\n unit += options.binary ? \"i\" : \"\";\n unit += options.bits ? \"bit\" : \"B\";\n }\n return prefix + numberString + \" \" + unit;\n}\nfunction getLocaleOptions({ maximumFractionDigits , minimumFractionDigits }) {\n if (maximumFractionDigits || minimumFractionDigits) {\n return {\n maximumFractionDigits,\n minimumFractionDigits\n };\n }\n}\n/**\n * Formats the given number using `Number#toLocaleString`.\n * - If locale is a string, the value is expected to be a locale-key (for example: `de`).\n * - If locale is true, the system default locale is used for translation.\n * - If no value for locale is specified, the number is returned unmodified.\n */ function toLocaleString(num, locale, options) {\n if (typeof locale === \"string\" || Array.isArray(locale)) {\n return num.toLocaleString(locale, options);\n } else if (locale === true || options !== undefined) {\n return num.toLocaleString(undefined, options);\n }\n return num.toString();\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L3ByZXR0eV9ieXRlc0B2MS4wLjUvbW9kLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUEwQkEsRUFLRyxBQUxIOzs7OztDQUtHLEFBTEgsRUFLRyxDQUNILE1BQU0sVUFBVSxXQUFXLENBQ3pCLEdBQVcsRUFDWCxPQUEyQixHQUFHLENBQUM7QUFBQSxDQUFDLEVBQ3hCLENBQUM7SUFDVCxFQUFFLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEdBQUcsQ0FBQztRQUMxQixLQUFLLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxHQUFHO0lBQ3pFLENBQUM7SUFFRCxLQUFLLENBQUMsaUJBQWlCLElBQUksT0FBTyxDQUFDLElBQUksR0FBRyxDQUFHLEtBQUcsQ0FBRyxNQUFJLENBQVU7SUFFakUsRUFBRSxFQUFFLE9BQU8sQ0FBQyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sRUFBRSxHQUFHLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUcsS0FBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUcsS0FBRyxDQUFFO0lBQ3pELEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUc7SUFFbEIsS0FBSyxDQUFDLGFBQWEsR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPO0lBRTlDLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDWixLQUFLLENBQUMsWUFBWSxHQUFHLGNBQWMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRSxhQUFhO1FBQ3RFLE1BQU0sQ0FBQyxNQUFNLEdBQUcsWUFBWSxHQUFHLENBQUcsS0FBRyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzFELENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQ3ZCLElBQUksQ0FBQyxLQUFLLENBQ1IsT0FBTyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBRXZFLGlCQUFpQixDQUFDLE1BQU0sR0FBRyxDQUFDO0lBRTlCLEdBQUcsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsSUFBSSxHQUFHLElBQUksRUFBRSxRQUFRO0lBRXRELEVBQUUsR0FBRyxhQUFhLEVBQUUsQ0FBQztRQUNuQixHQUFHLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVksR0FBRyxjQUFjLENBQ2pDLEdBQUcsRUFDSCxPQUFPLENBQUMsTUFBTSxFQUNkLGFBQWE7SUFHZixHQUFHLENBQUMsSUFBSSxHQUFHLGlCQUFpQixDQUFDLFFBQVE7SUFDckMsRUFBRSxFQUFFLFFBQVEsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNqQixJQUFJLElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFHLEtBQUcsQ0FBRTtRQUNqQyxJQUFJLElBQUksT0FBTyxDQUFDLElBQUksR0FBRyxDQUFLLE9BQUcsQ0FBRztJQUNwQyxDQUFDO0lBRUQsTUFBTSxDQUFDLE1BQU0sR0FBRyxZQUFZLEdBQUcsQ0FBRyxLQUFHLElBQUk7QUFDM0MsQ0FBQztTQUVRLGdCQUFnQixDQUN2QixDQUFDLENBQUMscUJBQXFCLEdBQUUscUJBQXFCLEVBQXFCLENBQUMsRUFDekMsQ0FBQztJQUM1QixFQUFFLEVBQUUscUJBQXFCLElBQUkscUJBQXFCLEVBQUUsQ0FBQztRQUNuRCxNQUFNLENBQUMsQ0FBQztZQUNOLHFCQUFxQjtZQUNyQixxQkFBcUI7UUFDdkIsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQsRUFLRyxBQUxIOzs7OztDQUtHLEFBTEgsRUFLRyxVQUNNLGNBQWMsQ0FDckIsR0FBVyxFQUNYLE1BQStDLEVBQy9DLE9BQWtDLEVBQzFCLENBQUM7SUFDVCxFQUFFLEVBQUUsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFRLFdBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUN4RCxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsT0FBTztJQUMzQyxDQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sS0FBSyxJQUFJLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3BELE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLFNBQVMsRUFBRSxPQUFPO0lBQzlDLENBQUM7SUFFRCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVE7QUFDckIsQ0FBQyJ9", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.108.0/http/server.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nimport { delay } from \"../async/mod.ts\";\n\n/** Thrown by Server after it has been closed. */\nconst ERROR_SERVER_CLOSED = \"Server closed\";\n\n/** Thrown when parsing an invalid address string. */\nconst ERROR_ADDRESS_INVALID = \"Invalid address\";\n\n/** Default port for serving HTTP. */\nconst HTTP_PORT = 80;\n\n/** Default port for serving HTTPS. */\nconst HTTPS_PORT = 443;\n\n/** Initial backoff delay of 5ms following a temporary accept failure. */\nconst INITIAL_ACCEPT_BACKOFF_DELAY = 5;\n\n/** Max backoff delay of 1s following a temporary accept failure. */\nconst MAX_ACCEPT_BACKOFF_DELAY = 1000;\n\n/** Information about the connection a request arrived on. */\nexport interface ConnInfo {\n /** The local address of the connection. */\n readonly localAddr: Deno.Addr;\n /** The remote address of the connection. */\n readonly remoteAddr: Deno.Addr;\n}\n\n/**\n * A handler for HTTP requests. Consumes a request and connection information\n * and returns a response.\n *\n * If a handler throws, the server calling the handler will assume the impact\n * of the error is isolated to the individual request. It will catch the error\n * and close the underlying connection.\n */\nexport type Handler = (\n request: Request,\n connInfo: ConnInfo,\n) => Response | Promise;\n\n/**\n * Parse an address from a string.\n *\n * Throws a `TypeError` when the address is invalid.\n *\n * ```ts\n * import { _parseAddrFromStr } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \"::1:8000\";\n * const listenOptions = _parseAddrFromStr(addr);\n * ```\n *\n * @param addr The address string to parse.\n * @param defaultPort Default port when not included in the address string.\n * @return The parsed address.\n */\nexport function _parseAddrFromStr(\n addr: string,\n defaultPort = HTTP_PORT,\n): Deno.ListenOptions {\n const host = addr.startsWith(\":\") ? `0.0.0.0${addr}` : addr;\n\n let url: URL;\n\n try {\n url = new URL(`http://${host}`);\n } catch {\n throw new TypeError(ERROR_ADDRESS_INVALID);\n }\n\n if (\n url.username ||\n url.password ||\n url.pathname != \"/\" ||\n url.search ||\n url.hash\n ) {\n throw new TypeError(ERROR_ADDRESS_INVALID);\n }\n\n return {\n hostname: url.hostname,\n port: url.port === \"\" ? defaultPort : Number(url.port),\n };\n}\n\n/** Options for running an HTTP server. */\nexport interface ServerInit {\n /**\n * Optionally specifies the address to listen on, in the form\n * \"host:port\".\n *\n * If the port is omitted, `:80` is used by default for HTTP when invoking\n * non-TLS methods such as `Server.listenAndServe`, and `:443` is\n * used by default for HTTPS when invoking TLS methods such as\n * `Server.listenAndServeTls`.\n *\n * If the host is omitted, the non-routable meta-address `0.0.0.0` is used.\n */\n addr?: string;\n\n /** The handler to invoke for individual HTTP requests. */\n handler: Handler;\n}\n\n/** Used to construct an HTTP server. */\nexport class Server {\n #addr?: string;\n #handler: Handler;\n #closed = false;\n #listeners: Set = new Set();\n #httpConnections: Set = new Set();\n\n /**\n * Constructs a new HTTP Server instance.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ addr, handler });\n * ```\n *\n * @param serverInit Options for running an HTTP server.\n */\n constructor(serverInit: ServerInit) {\n this.#addr = serverInit.addr;\n this.#handler = serverInit.handler;\n }\n\n /**\n * Accept incoming connections on the given listener, and handle requests on\n * these connections with the given handler.\n *\n * HTTP/2 support is only enabled if the provided Deno.Listener returns TLS\n * connections and was configured with \"h2\" in the ALPN protocols.\n *\n * Throws a server closed error if called after the server has been closed.\n *\n * Will always close the created listener.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ handler });\n * const listener = Deno.listen({ port: 4505 });\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await server.serve(listener);\n * ```\n *\n * @param listener The listener to accept connections from.\n */\n async serve(listener: Deno.Listener): Promise {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n\n this.#trackListener(listener);\n\n try {\n return await this.#accept(listener);\n } finally {\n this.#untrackListener(listener);\n\n try {\n listener.close();\n } catch {\n // Listener has already been closed.\n }\n }\n }\n\n /**\n * Create a listener on the server, accept incoming connections, and handle\n * requests on these connections with the given handler.\n *\n * If the server was constructed with the port omitted from the address, `:80`\n * is used.\n *\n * If the server was constructed with the host omitted from the address, the\n * non-routable meta-address `0.0.0.0` is used.\n *\n * Throws a server closed error if the server has been closed.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ addr, handler });\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await server.listenAndServe();\n * ```\n */\n async listenAndServe(): Promise {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n\n const addr = this.#addr ?? `:${HTTP_PORT}`;\n const listenOptions = _parseAddrFromStr(addr, HTTP_PORT);\n\n const listener = Deno.listen({\n ...listenOptions,\n transport: \"tcp\",\n });\n\n return await this.serve(listener);\n }\n\n /**\n * Create a listener on the server, accept incoming connections, upgrade them\n * to TLS, and handle requests on these connections with the given handler.\n *\n * If the server was constructed with the port omitted from the address, `:443`\n * is used.\n *\n * If the server was constructed with the host omitted from the address, the\n * non-routable meta-address `0.0.0.0` is used.\n *\n * Throws a server closed error if the server has been closed.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ addr, handler });\n *\n * const certFile = \"/path/to/certFile.crt\";\n * const keyFile = \"/path/to/keyFile.key\";\n *\n * console.log(\"server listening on https://localhost:4505\");\n *\n * await server.listenAndServeTls(certFile, keyFile);\n * ```\n *\n * @param certFile The path to the file containing the TLS certificate.\n * @param keyFile The path to the file containing the TLS private key.\n */\n async listenAndServeTls(certFile: string, keyFile: string): Promise {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n\n const addr = this.#addr ?? `:${HTTPS_PORT}`;\n const listenOptions = _parseAddrFromStr(addr, HTTPS_PORT);\n\n const listener = Deno.listenTls({\n ...listenOptions,\n certFile,\n keyFile,\n transport: \"tcp\",\n // ALPN protocol support not yet stable.\n // alpnProtocols: [\"h2\", \"http/1.1\"],\n });\n\n return await this.serve(listener);\n }\n\n /**\n * Immediately close the server listeners and associated HTTP connections.\n *\n * Throws a server closed error if called after the server has been closed.\n */\n close(): void {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n\n this.#closed = true;\n\n for (const listener of this.#listeners) {\n try {\n listener.close();\n } catch {\n // Listener has already been closed.\n }\n }\n\n this.#listeners.clear();\n\n for (const httpConn of this.#httpConnections) {\n this.#closeHttpConn(httpConn);\n }\n\n this.#httpConnections.clear();\n }\n\n /** Get whether the server is closed. */\n get closed(): boolean {\n return this.#closed;\n }\n\n /** Get the list of network addresses the server is listening on. */\n get addrs(): Deno.Addr[] {\n return Array.from(this.#listeners).map((listener) => listener.addr);\n }\n\n /**\n * Responds to an HTTP request.\n *\n * @param requestEvent The HTTP request to respond to.\n * @param httpCon The HTTP connection to yield requests from.\n * @param connInfo Information about the underlying connection.\n */\n async #respond(\n requestEvent: Deno.RequestEvent,\n httpCon: Deno.HttpConn,\n connInfo: ConnInfo,\n ): Promise {\n try {\n // Handle the request event, generating a response.\n const response = await this.#handler(\n requestEvent.request,\n connInfo,\n );\n\n // Send the response.\n await requestEvent.respondWith(response);\n } catch {\n // If the handler throws then it is assumed that the impact of the error\n // is isolated to the individual request, so we close the connection.\n //\n // Alternatively the connection has already been closed, or there is some\n // other error with responding on this connection that prompts us to\n // close it and open a new connection.\n return this.#closeHttpConn(httpCon);\n }\n }\n\n /**\n * Serves all HTTP requests on a single connection.\n *\n * @param httpConn The HTTP connection to yield requests from.\n * @param connInfo Information about the underlying connection.\n */\n async #serveHttp(\n httpConn: Deno.HttpConn,\n connInfo: ConnInfo,\n ): Promise {\n while (!this.#closed) {\n let requestEvent: Deno.RequestEvent | null;\n\n try {\n // Yield the new HTTP request on the connection.\n requestEvent = await httpConn.nextRequest();\n } catch {\n // Connection has been closed.\n break;\n }\n\n if (requestEvent === null) {\n // Connection has been closed.\n break;\n }\n\n // Respond to the request. Note we do not await this async method to\n // allow the connection to handle multiple requests in the case of h2.\n this.#respond(requestEvent, httpConn, connInfo);\n }\n\n this.#closeHttpConn(httpConn);\n }\n\n /**\n * Accepts all connections on a single network listener.\n *\n * @param listener The listener to accept connections from.\n */\n async #accept(\n listener: Deno.Listener,\n ): Promise {\n let acceptBackoffDelay: number | undefined;\n\n while (!this.#closed) {\n let conn: Deno.Conn;\n\n try {\n // Wait for a new connection.\n conn = await listener.accept();\n } catch (error) {\n if (\n // The listener is closed.\n error instanceof Deno.errors.BadResource ||\n // TLS handshake errors.\n error instanceof Deno.errors.InvalidData ||\n error instanceof Deno.errors.UnexpectedEof ||\n error instanceof Deno.errors.ConnectionReset ||\n error instanceof Deno.errors.NotConnected\n ) {\n // Backoff after transient errors to allow time for the system to\n // recover, and avoid blocking up the event loop with a continuously\n // running loop.\n if (!acceptBackoffDelay) {\n acceptBackoffDelay = INITIAL_ACCEPT_BACKOFF_DELAY;\n } else {\n acceptBackoffDelay *= 2;\n }\n\n if (acceptBackoffDelay >= MAX_ACCEPT_BACKOFF_DELAY) {\n acceptBackoffDelay = MAX_ACCEPT_BACKOFF_DELAY;\n }\n\n await delay(acceptBackoffDelay);\n\n continue;\n }\n\n throw error;\n }\n\n acceptBackoffDelay = undefined;\n\n // \"Upgrade\" the network connection into an HTTP connection.\n let httpConn: Deno.HttpConn;\n\n try {\n httpConn = Deno.serveHttp(conn);\n } catch {\n // Connection has been closed.\n continue;\n }\n\n // Closing the underlying listener will not close HTTP connections, so we\n // track for closure upon server close.\n this.#trackHttpConnection(httpConn);\n\n const connInfo: ConnInfo = {\n localAddr: conn.localAddr,\n remoteAddr: conn.remoteAddr,\n };\n\n // Serve the requests that arrive on the just-accepted connection. Note\n // we do not await this async method to allow the server to accept new\n // connections.\n this.#serveHttp(httpConn, connInfo);\n }\n }\n\n /**\n * Untracks and closes an HTTP connection.\n *\n * @param httpConn The HTTP connection to close.\n */\n #closeHttpConn(httpConn: Deno.HttpConn): void {\n this.#untrackHttpConnection(httpConn);\n\n try {\n httpConn.close();\n } catch {\n // Connection has already been closed.\n }\n }\n\n /**\n * Adds the listener to the internal tracking list.\n *\n * @param listener Listener to track.\n */\n #trackListener(listener: Deno.Listener): void {\n this.#listeners.add(listener);\n }\n\n /**\n * Removes the listener from the internal tracking list.\n *\n * @param listener Listener to untrack.\n */\n #untrackListener(listener: Deno.Listener): void {\n this.#listeners.delete(listener);\n }\n\n /**\n * Adds the HTTP connection to the internal tracking list.\n *\n * @param httpConn HTTP connection to track.\n */\n #trackHttpConnection(httpConn: Deno.HttpConn): void {\n this.#httpConnections.add(httpConn);\n }\n\n /**\n * Removes the HTTP connection from the internal tracking list.\n *\n * @param httpConn HTTP connection to untrack.\n */\n #untrackHttpConnection(httpConn: Deno.HttpConn): void {\n this.#httpConnections.delete(httpConn);\n }\n}\n\n/** Additional serve options. */\nexport interface ServeInit {\n /** An AbortSignal to close the server and all connections. */\n signal?: AbortSignal;\n}\n\n/**\n * Constructs a server, accepts incoming connections on the given listener, and\n * handles requests on these connections with the given handler.\n *\n * ```ts\n * import { serve } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const listener = Deno.listen({ port: 4505 });\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await serve(listener, (request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * });\n * ```\n *\n * @param listener The listener to accept connections from.\n * @param handler The handler for individual HTTP requests.\n * @param options Optional serve options.\n */\nexport async function serve(\n listener: Deno.Listener,\n handler: Handler,\n options?: ServeInit,\n): Promise {\n const server = new Server({ handler });\n\n if (options?.signal) {\n options.signal.onabort = () => server.close();\n }\n\n return await server.serve(listener);\n}\n\n/**\n * Constructs a server, creates a listener on the given address, accepts\n * incoming connections, and handles requests on these connections with the\n * given handler.\n *\n * If the port is omitted from the address, `:80` is used.\n *\n * If the host is omitted from the address, the non-routable meta-address\n * `0.0.0.0` is used.\n *\n * ```ts\n * import { listenAndServe } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await listenAndServe(addr, (request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * });\n * ```\n *\n * @param addr The address to listen on.\n * @param handler The handler for individual HTTP requests.\n * @param options Optional serve options.\n */\nexport async function listenAndServe(\n addr: string,\n handler: Handler,\n options?: ServeInit,\n): Promise {\n const server = new Server({ addr, handler });\n\n if (options?.signal) {\n options.signal.onabort = () => server.close();\n }\n\n return await server.listenAndServe();\n}\n\n/**\n * Constructs a server, creates a listener on the given address, accepts\n * incoming connections, upgrades them to TLS, and handles requests on these\n * connections with the given handler.\n *\n * If the port is omitted from the address, `:443` is used.\n *\n * If the host is omitted from the address, the non-routable meta-address\n * `0.0.0.0` is used.\n *\n * ```ts\n * import { listenAndServeTls } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const certFile = \"/path/to/certFile.crt\";\n * const keyFile = \"/path/to/keyFile.key\";\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await listenAndServeTls(addr, certFile, keyFile, (request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * });\n * ```\n *\n * @param addr The address to listen on.\n * @param certFile The path to the file containing the TLS certificate.\n * @param keyFile The path to the file containing the TLS private key.\n * @param handler The handler for individual HTTP requests.\n * @param options Optional serve options.\n */\nexport async function listenAndServeTls(\n addr: string,\n certFile: string,\n keyFile: string,\n handler: Handler,\n options?: ServeInit,\n): Promise {\n const server = new Server({ addr, handler });\n\n if (options?.signal) {\n options.signal.onabort = () => server.close();\n }\n\n return await server.listenAndServeTls(certFile, keyFile);\n}\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nimport { delay } from \"../async/mod.ts\";\n/** Thrown by Server after it has been closed. */ const ERROR_SERVER_CLOSED = \"Server closed\";\n/** Thrown when parsing an invalid address string. */ const ERROR_ADDRESS_INVALID = \"Invalid address\";\n/** Default port for serving HTTP. */ const HTTP_PORT = 80;\n/** Default port for serving HTTPS. */ const HTTPS_PORT = 443;\n/** Initial backoff delay of 5ms following a temporary accept failure. */ const INITIAL_ACCEPT_BACKOFF_DELAY = 5;\n/** Max backoff delay of 1s following a temporary accept failure. */ const MAX_ACCEPT_BACKOFF_DELAY = 1000;\n/**\n * Parse an address from a string.\n *\n * Throws a `TypeError` when the address is invalid.\n *\n * ```ts\n * import { _parseAddrFromStr } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \"::1:8000\";\n * const listenOptions = _parseAddrFromStr(addr);\n * ```\n *\n * @param addr The address string to parse.\n * @param defaultPort Default port when not included in the address string.\n * @return The parsed address.\n */ export function _parseAddrFromStr(addr, defaultPort = HTTP_PORT) {\n const host = addr.startsWith(\":\") ? `0.0.0.0${addr}` : addr;\n let url;\n try {\n url = new URL(`http://${host}`);\n } catch {\n throw new TypeError(ERROR_ADDRESS_INVALID);\n }\n if (url.username || url.password || url.pathname != \"/\" || url.search || url.hash) {\n throw new TypeError(ERROR_ADDRESS_INVALID);\n }\n return {\n hostname: url.hostname,\n port: url.port === \"\" ? defaultPort : Number(url.port)\n };\n}\n/** Used to construct an HTTP server. */ export class Server {\n #addr;\n #handler;\n #closed = false;\n #listeners = new Set();\n #httpConnections = new Set();\n /**\n * Constructs a new HTTP Server instance.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ addr, handler });\n * ```\n *\n * @param serverInit Options for running an HTTP server.\n */ constructor(serverInit){\n this.#addr = serverInit.addr;\n this.#handler = serverInit.handler;\n }\n /**\n * Accept incoming connections on the given listener, and handle requests on\n * these connections with the given handler.\n *\n * HTTP/2 support is only enabled if the provided Deno.Listener returns TLS\n * connections and was configured with \"h2\" in the ALPN protocols.\n *\n * Throws a server closed error if called after the server has been closed.\n *\n * Will always close the created listener.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ handler });\n * const listener = Deno.listen({ port: 4505 });\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await server.serve(listener);\n * ```\n *\n * @param listener The listener to accept connections from.\n */ async serve(listener) {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n this.#trackListener(listener);\n try {\n return await this.#accept(listener);\n } finally{\n this.#untrackListener(listener);\n try {\n listener.close();\n } catch {\n // Listener has already been closed.\n }\n }\n }\n /**\n * Create a listener on the server, accept incoming connections, and handle\n * requests on these connections with the given handler.\n *\n * If the server was constructed with the port omitted from the address, `:80`\n * is used.\n *\n * If the server was constructed with the host omitted from the address, the\n * non-routable meta-address `0.0.0.0` is used.\n *\n * Throws a server closed error if the server has been closed.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ addr, handler });\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await server.listenAndServe();\n * ```\n */ async listenAndServe() {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n const addr = this.#addr ?? `:${HTTP_PORT}`;\n const listenOptions = _parseAddrFromStr(addr, HTTP_PORT);\n const listener = Deno.listen({\n ...listenOptions,\n transport: \"tcp\"\n });\n return await this.serve(listener);\n }\n /**\n * Create a listener on the server, accept incoming connections, upgrade them\n * to TLS, and handle requests on these connections with the given handler.\n *\n * If the server was constructed with the port omitted from the address, `:443`\n * is used.\n *\n * If the server was constructed with the host omitted from the address, the\n * non-routable meta-address `0.0.0.0` is used.\n *\n * Throws a server closed error if the server has been closed.\n *\n * ```ts\n * import { Server } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const handler = (request: Request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * };\n *\n * const server = new Server({ addr, handler });\n *\n * const certFile = \"/path/to/certFile.crt\";\n * const keyFile = \"/path/to/keyFile.key\";\n *\n * console.log(\"server listening on https://localhost:4505\");\n *\n * await server.listenAndServeTls(certFile, keyFile);\n * ```\n *\n * @param certFile The path to the file containing the TLS certificate.\n * @param keyFile The path to the file containing the TLS private key.\n */ async listenAndServeTls(certFile, keyFile) {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n const addr = this.#addr ?? `:${HTTPS_PORT}`;\n const listenOptions = _parseAddrFromStr(addr, HTTPS_PORT);\n const listener = Deno.listenTls({\n ...listenOptions,\n certFile,\n keyFile,\n transport: \"tcp\"\n });\n return await this.serve(listener);\n }\n /**\n * Immediately close the server listeners and associated HTTP connections.\n *\n * Throws a server closed error if called after the server has been closed.\n */ close() {\n if (this.#closed) {\n throw new Deno.errors.Http(ERROR_SERVER_CLOSED);\n }\n this.#closed = true;\n for (const listener of this.#listeners){\n try {\n listener.close();\n } catch {\n // Listener has already been closed.\n }\n }\n this.#listeners.clear();\n for (const httpConn of this.#httpConnections){\n this.#closeHttpConn(httpConn);\n }\n this.#httpConnections.clear();\n }\n /** Get whether the server is closed. */ get closed() {\n return this.#closed;\n }\n /** Get the list of network addresses the server is listening on. */ get addrs() {\n return Array.from(this.#listeners).map((listener)=>listener.addr\n );\n }\n /**\n * Responds to an HTTP request.\n *\n * @param requestEvent The HTTP request to respond to.\n * @param httpCon The HTTP connection to yield requests from.\n * @param connInfo Information about the underlying connection.\n */ async #respond(requestEvent, httpCon, connInfo) {\n try {\n // Handle the request event, generating a response.\n const response = await this.#handler(requestEvent.request, connInfo);\n // Send the response.\n await requestEvent.respondWith(response);\n } catch {\n // If the handler throws then it is assumed that the impact of the error\n // is isolated to the individual request, so we close the connection.\n //\n // Alternatively the connection has already been closed, or there is some\n // other error with responding on this connection that prompts us to\n // close it and open a new connection.\n return this.#closeHttpConn(httpCon);\n }\n }\n /**\n * Serves all HTTP requests on a single connection.\n *\n * @param httpConn The HTTP connection to yield requests from.\n * @param connInfo Information about the underlying connection.\n */ async #serveHttp(httpConn, connInfo) {\n while(!this.#closed){\n let requestEvent;\n try {\n // Yield the new HTTP request on the connection.\n requestEvent = await httpConn.nextRequest();\n } catch {\n break;\n }\n if (requestEvent === null) {\n break;\n }\n // Respond to the request. Note we do not await this async method to\n // allow the connection to handle multiple requests in the case of h2.\n this.#respond(requestEvent, httpConn, connInfo);\n }\n this.#closeHttpConn(httpConn);\n }\n /**\n * Accepts all connections on a single network listener.\n *\n * @param listener The listener to accept connections from.\n */ async #accept(listener) {\n let acceptBackoffDelay;\n while(!this.#closed){\n let conn;\n try {\n // Wait for a new connection.\n conn = await listener.accept();\n } catch (error) {\n if (// The listener is closed.\n error instanceof Deno.errors.BadResource || // TLS handshake errors.\n error instanceof Deno.errors.InvalidData || error instanceof Deno.errors.UnexpectedEof || error instanceof Deno.errors.ConnectionReset || error instanceof Deno.errors.NotConnected) {\n // Backoff after transient errors to allow time for the system to\n // recover, and avoid blocking up the event loop with a continuously\n // running loop.\n if (!acceptBackoffDelay) {\n acceptBackoffDelay = INITIAL_ACCEPT_BACKOFF_DELAY;\n } else {\n acceptBackoffDelay *= 2;\n }\n if (acceptBackoffDelay >= MAX_ACCEPT_BACKOFF_DELAY) {\n acceptBackoffDelay = MAX_ACCEPT_BACKOFF_DELAY;\n }\n await delay(acceptBackoffDelay);\n continue;\n }\n throw error;\n }\n acceptBackoffDelay = undefined;\n // \"Upgrade\" the network connection into an HTTP connection.\n let httpConn;\n try {\n httpConn = Deno.serveHttp(conn);\n } catch {\n continue;\n }\n // Closing the underlying listener will not close HTTP connections, so we\n // track for closure upon server close.\n this.#trackHttpConnection(httpConn);\n const connInfo = {\n localAddr: conn.localAddr,\n remoteAddr: conn.remoteAddr\n };\n // Serve the requests that arrive on the just-accepted connection. Note\n // we do not await this async method to allow the server to accept new\n // connections.\n this.#serveHttp(httpConn, connInfo);\n }\n }\n /**\n * Untracks and closes an HTTP connection.\n *\n * @param httpConn The HTTP connection to close.\n */ #closeHttpConn(httpConn) {\n this.#untrackHttpConnection(httpConn);\n try {\n httpConn.close();\n } catch {\n // Connection has already been closed.\n }\n }\n /**\n * Adds the listener to the internal tracking list.\n *\n * @param listener Listener to track.\n */ #trackListener(listener) {\n this.#listeners.add(listener);\n }\n /**\n * Removes the listener from the internal tracking list.\n *\n * @param listener Listener to untrack.\n */ #untrackListener(listener) {\n this.#listeners.delete(listener);\n }\n /**\n * Adds the HTTP connection to the internal tracking list.\n *\n * @param httpConn HTTP connection to track.\n */ #trackHttpConnection(httpConn) {\n this.#httpConnections.add(httpConn);\n }\n /**\n * Removes the HTTP connection from the internal tracking list.\n *\n * @param httpConn HTTP connection to untrack.\n */ #untrackHttpConnection(httpConn) {\n this.#httpConnections.delete(httpConn);\n }\n}\n/**\n * Constructs a server, accepts incoming connections on the given listener, and\n * handles requests on these connections with the given handler.\n *\n * ```ts\n * import { serve } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const listener = Deno.listen({ port: 4505 });\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await serve(listener, (request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * });\n * ```\n *\n * @param listener The listener to accept connections from.\n * @param handler The handler for individual HTTP requests.\n * @param options Optional serve options.\n */ export async function serve(listener, handler, options) {\n const server = new Server({\n handler\n });\n if (options?.signal) {\n options.signal.onabort = ()=>server.close()\n ;\n }\n return await server.serve(listener);\n}\n/**\n * Constructs a server, creates a listener on the given address, accepts\n * incoming connections, and handles requests on these connections with the\n * given handler.\n *\n * If the port is omitted from the address, `:80` is used.\n *\n * If the host is omitted from the address, the non-routable meta-address\n * `0.0.0.0` is used.\n *\n * ```ts\n * import { listenAndServe } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await listenAndServe(addr, (request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * });\n * ```\n *\n * @param addr The address to listen on.\n * @param handler The handler for individual HTTP requests.\n * @param options Optional serve options.\n */ export async function listenAndServe(addr, handler, options) {\n const server = new Server({\n addr,\n handler\n });\n if (options?.signal) {\n options.signal.onabort = ()=>server.close()\n ;\n }\n return await server.listenAndServe();\n}\n/**\n * Constructs a server, creates a listener on the given address, accepts\n * incoming connections, upgrades them to TLS, and handles requests on these\n * connections with the given handler.\n *\n * If the port is omitted from the address, `:443` is used.\n *\n * If the host is omitted from the address, the non-routable meta-address\n * `0.0.0.0` is used.\n *\n * ```ts\n * import { listenAndServeTls } from \"https://deno.land/std@$STD_VERSION/http/server.ts\";\n *\n * const addr = \":4505\";\n * const certFile = \"/path/to/certFile.crt\";\n * const keyFile = \"/path/to/keyFile.key\";\n *\n * console.log(\"server listening on http://localhost:4505\");\n *\n * await listenAndServeTls(addr, certFile, keyFile, (request) => {\n * const body = `Your user-agent is:\\n\\n${request.headers.get(\n * \"user-agent\",\n * ) ?? \"Unknown\"}`;\n *\n * return new Response(body, { status: 200 });\n * });\n * ```\n *\n * @param addr The address to listen on.\n * @param certFile The path to the file containing the TLS certificate.\n * @param keyFile The path to the file containing the TLS private key.\n * @param handler The handler for individual HTTP requests.\n * @param options Optional serve options.\n */ export async function listenAndServeTls(addr, certFile, keyFile, handler, options) {\n const server = new Server({\n addr,\n handler\n });\n if (options?.signal) {\n options.signal.onabort = ()=>server.close()\n ;\n }\n return await server.listenAndServeTls(certFile, keyFile);\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9odHRwL3NlcnZlci50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsRUFBMEUsQUFBMUUsd0VBQTBFO0FBQzFFLE1BQU0sR0FBRyxLQUFLLFFBQVEsQ0FBaUI7QUFFdkMsRUFBaUQsQUFBakQsNkNBQWlELEFBQWpELEVBQWlELENBQ2pELEtBQUssQ0FBQyxtQkFBbUIsR0FBRyxDQUFlO0FBRTNDLEVBQXFELEFBQXJELGlEQUFxRCxBQUFyRCxFQUFxRCxDQUNyRCxLQUFLLENBQUMscUJBQXFCLEdBQUcsQ0FBaUI7QUFFL0MsRUFBcUMsQUFBckMsaUNBQXFDLEFBQXJDLEVBQXFDLENBQ3JDLEtBQUssQ0FBQyxTQUFTLEdBQUcsRUFBRTtBQUVwQixFQUFzQyxBQUF0QyxrQ0FBc0MsQUFBdEMsRUFBc0MsQ0FDdEMsS0FBSyxDQUFDLFVBQVUsR0FBRyxHQUFHO0FBRXRCLEVBQXlFLEFBQXpFLHFFQUF5RSxBQUF6RSxFQUF5RSxDQUN6RSxLQUFLLENBQUMsNEJBQTRCLEdBQUcsQ0FBQztBQUV0QyxFQUFvRSxBQUFwRSxnRUFBb0UsQUFBcEUsRUFBb0UsQ0FDcEUsS0FBSyxDQUFDLHdCQUF3QixHQUFHLElBQUk7QUF1QnJDLEVBZUcsQUFmSDs7Ozs7Ozs7Ozs7Ozs7O0NBZUcsQUFmSCxFQWVHLENBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixJQUFZLEVBQ1osV0FBVyxHQUFHLFNBQVMsRUFDSCxDQUFDO0lBQ3JCLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFHLE9BQUssT0FBTyxFQUFFLElBQUksS0FBSyxJQUFJO0lBRTNELEdBQUcsQ0FBQyxHQUFHO0lBRVAsR0FBRyxDQUFDLENBQUM7UUFDSCxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsSUFBSTtJQUM5QixDQUFDLENBQUMsS0FBSyxFQUFDLENBQUM7UUFDUCxLQUFLLENBQUMsR0FB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", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/std@0.108.0/async/mod.ts"] - } - }, - "https://deno.land/std@0.108.0/async/mod.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nexport * from \"./debounce.ts\";\nexport * from \"./deferred.ts\";\nexport * from \"./delay.ts\";\nexport * from \"./mux_async_iterator.ts\";\nexport * from \"./pool.ts\";\nexport * from \"./tee.ts\";\nexport * from \"./deadline.ts\";\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nexport * from \"./debounce.ts\";\nexport * from \"./deferred.ts\";\nexport * from \"./delay.ts\";\nexport * from \"./mux_async_iterator.ts\";\nexport * from \"./pool.ts\";\nexport * from \"./tee.ts\";\nexport * from \"./deadline.ts\";\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMDguMC9hc3luYy9tb2QudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEVBQTBFLEFBQTFFLHdFQUEwRTtjQUM1RCxDQUFlO2NBQ2YsQ0FBZTtjQUNmLENBQVk7Y0FDWixDQUF5QjtjQUN6QixDQUFXO2NBQ1gsQ0FBVTtjQUNWLENBQWUifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": [ - "https://deno.land/std@0.108.0/async/debounce.ts", - "https://deno.land/std@0.108.0/async/deferred.ts", - "https://deno.land/std@0.108.0/async/delay.ts", - "https://deno.land/std@0.108.0/async/mux_async_iterator.ts", - "https://deno.land/std@0.108.0/async/pool.ts", - "https://deno.land/std@0.108.0/async/tee.ts", - "https://deno.land/std@0.108.0/async/deadline.ts" - ] - } - }, - "file:///src/worker/vscode.ts": { - "Source": { - "source": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */\n\nimport { match } from \"https://deno.land/x/path_to_regexp@v6.2.0/index.ts\";\nimport { S3_BUCKET } from \"./registry.ts\";\n\nconst VERSIONS = match(\"/_vsc1/modules/:module([a-z0-9_]*)\");\nconst PATHS = match(\"/_vsc1/modules/:module([a-z0-9_]*)/v/:version\");\nconst PATHS_LATEST = match(\"/_vsc1/modules/:module([a-z0-9_]*)/v_latest\");\n\n/**\n * /_vsc1/modules/:module returns a list of all versions for a module\n *\n * /_vsc1/modules/:module/v/:version returns a list of all code files for a version of module\n *\n * /_vsc1/modules/:module/v_latest returns a list of all code files for the latest version of module\n */\nexport async function handleVSCRequest(url: URL): Promise {\n const pathname = url.pathname;\n\n const versions = VERSIONS(pathname);\n if (versions) {\n const module = (versions.params as Record)[\"module\"];\n const resp = await fetch(`${S3_BUCKET}${module}/meta/versions.json`);\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"module not found\", { status: 404 });\n }\n if (!resp.ok) {\n return new Response(\"internal server error 1\", { status: 500 });\n }\n const json = await resp.json();\n return new Response(JSON.stringify(json.versions), {\n status: 200,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": \"max-age=86400\",\n },\n });\n }\n\n const paths = PATHS(pathname);\n if (paths) {\n const module = (paths.params as Record)[\"module\"];\n const version = (paths.params as Record)[\"version\"];\n return getPaths(module, version);\n }\n\n const pathsLatest = PATHS_LATEST(pathname);\n if (pathsLatest) {\n const module = (pathsLatest.params as Record)[\"module\"];\n const resp = await fetch(`${S3_BUCKET}${module}/meta/versions.json`);\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"module not found\", { status: 404 });\n }\n if (!resp.ok) {\n return new Response(\"internal server error 3\", { status: 500 });\n }\n const json = await resp.json();\n if (!json.latest) return new Response(\"no latest version\", { status: 404 });\n return getPaths(module, json.latest);\n }\n\n return new Response(\"not found\", { status: 404 });\n}\n\nasync function getPaths(module: string, version: string): Promise {\n const resp = await fetch(\n `${S3_BUCKET}${module}/versions/${version}/meta/meta.json`,\n );\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"module or version not found\", { status: 404 });\n }\n if (!resp.ok) return new Response(\"internal server error 2\", { status: 500 });\n const json = await resp.json();\n const list = (json.directory_listing as Array>)\n .filter((f) => f.type === \"file\" && !f.path.includes(\"/_\"))\n .map((f) => f.path.substring(1))\n .filter(\n (f) =>\n f.endsWith(\".jsx\") ||\n f.endsWith(\".jsx\") ||\n f.endsWith(\".ts\") ||\n f.endsWith(\".tsx\") ||\n f.endsWith(\".mjs\"),\n );\n return new Response(JSON.stringify(list), {\n status: 200,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": \"max-age=86400\",\n },\n });\n}\n", - "transpiled": "/* Copyright 2020 the Deno authors. All rights reserved. MIT license. */ import { match } from \"https://deno.land/x/path_to_regexp@v6.2.0/index.ts\";\nimport { S3_BUCKET } from \"./registry.ts\";\nconst VERSIONS = match(\"/_vsc1/modules/:module([a-z0-9_]*)\");\nconst PATHS = match(\"/_vsc1/modules/:module([a-z0-9_]*)/v/:version\");\nconst PATHS_LATEST = match(\"/_vsc1/modules/:module([a-z0-9_]*)/v_latest\");\n/**\n * /_vsc1/modules/:module returns a list of all versions for a module\n *\n * /_vsc1/modules/:module/v/:version returns a list of all code files for a version of module\n *\n * /_vsc1/modules/:module/v_latest returns a list of all code files for the latest version of module\n */ export async function handleVSCRequest(url) {\n const pathname = url.pathname;\n const versions = VERSIONS(pathname);\n if (versions) {\n const module = versions.params[\"module\"];\n const resp = await fetch(`${S3_BUCKET}${module}/meta/versions.json`);\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"module not found\", {\n status: 404\n });\n }\n if (!resp.ok) {\n return new Response(\"internal server error 1\", {\n status: 500\n });\n }\n const json = await resp.json();\n return new Response(JSON.stringify(json.versions), {\n status: 200,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": \"max-age=86400\"\n }\n });\n }\n const paths = PATHS(pathname);\n if (paths) {\n const module = paths.params[\"module\"];\n const version = paths.params[\"version\"];\n return getPaths(module, version);\n }\n const pathsLatest = PATHS_LATEST(pathname);\n if (pathsLatest) {\n const module = pathsLatest.params[\"module\"];\n const resp = await fetch(`${S3_BUCKET}${module}/meta/versions.json`);\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"module not found\", {\n status: 404\n });\n }\n if (!resp.ok) {\n return new Response(\"internal server error 3\", {\n status: 500\n });\n }\n const json = await resp.json();\n if (!json.latest) return new Response(\"no latest version\", {\n status: 404\n });\n return getPaths(module, json.latest);\n }\n return new Response(\"not found\", {\n status: 404\n });\n}\nasync function getPaths(module, version) {\n const resp = await fetch(`${S3_BUCKET}${module}/versions/${version}/meta/meta.json`);\n if (resp.status === 403 || resp.status === 404) {\n return new Response(\"module or version not found\", {\n status: 404\n });\n }\n if (!resp.ok) return new Response(\"internal server error 2\", {\n status: 500\n });\n const json = await resp.json();\n const list = json.directory_listing.filter((f)=>f.type === \"file\" && !f.path.includes(\"/_\")\n ).map((f)=>f.path.substring(1)\n ).filter((f)=>f.endsWith(\".jsx\") || f.endsWith(\".jsx\") || f.endsWith(\".ts\") || f.endsWith(\".tsx\") || f.endsWith(\".mjs\")\n );\n return new Response(JSON.stringify(list), {\n status: 200,\n headers: {\n \"content-type\": \"application/json\",\n \"cache-control\": \"max-age=86400\"\n }\n });\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxmaWxlOi8vL3NyYy93b3JrZXIvdnNjb2RlLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQUF3RSxBQUF4RSxvRUFBd0UsQUFBeEUsRUFBd0UsQ0FFeEUsTUFBTSxHQUFHLEtBQUssUUFBUSxDQUFvRDtBQUMxRSxNQUFNLEdBQUcsU0FBUyxRQUFRLENBQWU7QUFFekMsS0FBSyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsQ0FBb0M7QUFDM0QsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBK0M7QUFDbkUsS0FBSyxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUMsQ0FBNkM7QUFFeEUsRUFNRyxBQU5IOzs7Ozs7Q0FNRyxBQU5ILEVBTUcsQ0FDSCxNQUFNLGdCQUFnQixnQkFBZ0IsQ0FBQyxHQUFRLEVBQXFCLENBQUM7SUFDbkUsS0FBSyxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUMsUUFBUTtJQUU3QixLQUFLLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxRQUFRO0lBQ2xDLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQztRQUNiLEtBQUssQ0FBQyxNQUFNLEdBQUksUUFBUSxDQUFDLE1BQU0sQ0FBNEIsQ0FBUTtRQUNuRSxLQUFLLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxLQUFLLElBQUksU0FBUyxHQUFHLE1BQU0sQ0FBQyxtQkFBbUI7UUFDbEUsRUFBRSxFQUFFLElBQUksQ0FBQyxNQUFNLEtBQUssR0FBRyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDL0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBa0IsbUJBQUUsQ0FBQztnQkFBQyxNQUFNLEVBQUUsR0FBRztZQUFDLENBQUM7UUFDekQsQ0FBQztRQUNELEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDYixNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUF5QiwwQkFBRSxDQUFDO2dCQUFDLE1B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", - "content_type": null, - "deps": [ - "https://deno.land/x/path_to_regexp@v6.2.0/index.ts", - "file:///src/worker/registry.ts" - ] - } - }, - "https://deno.land/std@0.120.0/async/debounce.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n/**\n * A debounced function that will be delayed by a given `wait`\n * time in milliseconds. If the method is called again before\n * the timeout expires, the previous call will be aborted.\n */\nexport interface DebouncedFunction> {\n (...args: T): void;\n /** Clears the debounce timeout and omits calling the debounced function. */\n clear(): void;\n /** Clears the debounce timeout and calls the debounced function immediately. */\n flush(): void;\n /** Returns a boolean wether a debounce call is pending or not. */\n readonly pending: boolean;\n}\n\n/**\n * Creates a debounced function that delays the given `func`\n * by a given `wait` time in milliseconds. If the method is called\n * again before the timeout expires, the previous call will be\n * aborted.\n *\n * ```\n * import { debounce } from \"./debounce.ts\";\n *\n * const log = debounce(\n * (event: Deno.FsEvent) =>\n * console.log(\"[%s] %s\", event.kind, event.paths[0]),\n * 200,\n * );\n *\n * for await (const event of Deno.watchFs(\"./\")) {\n * log(event);\n * }\n * ```\n *\n * @param fn The function to debounce.\n * @param wait The time in milliseconds to delay the function.\n */\n// deno-lint-ignore no-explicit-any\nexport function debounce>(\n fn: (this: DebouncedFunction, ...args: T) => void,\n wait: number,\n): DebouncedFunction {\n let timeout: number | null = null;\n let flush: (() => void) | null = null;\n\n const debounced: DebouncedFunction = ((...args: T): void => {\n debounced.clear();\n flush = (): void => {\n debounced.clear();\n fn.call(debounced, ...args);\n };\n timeout = setTimeout(flush, wait);\n }) as DebouncedFunction;\n\n debounced.clear = (): void => {\n if (typeof timeout === \"number\") {\n clearTimeout(timeout);\n timeout = null;\n flush = null;\n }\n };\n\n debounced.flush = (): void => {\n flush?.();\n };\n\n Object.defineProperty(debounced, \"pending\", {\n get: () => typeof timeout === \"number\",\n });\n\n return debounced;\n}\n", - "transpiled": "/**\n * Creates a debounced function that delays the given `func`\n * by a given `wait` time in milliseconds. If the method is called\n * again before the timeout expires, the previous call will be\n * aborted.\n *\n * ```\n * import { debounce } from \"./debounce.ts\";\n *\n * const log = debounce(\n * (event: Deno.FsEvent) =>\n * console.log(\"[%s] %s\", event.kind, event.paths[0]),\n * 200,\n * );\n *\n * for await (const event of Deno.watchFs(\"./\")) {\n * log(event);\n * }\n * ```\n *\n * @param fn The function to debounce.\n * @param wait The time in milliseconds to delay the function.\n */ // deno-lint-ignore no-explicit-any\nexport function debounce(fn, wait) {\n let timeout = null;\n let flush = null;\n const debounced = (...args)=>{\n debounced.clear();\n flush = ()=>{\n debounced.clear();\n fn.call(debounced, ...args);\n };\n timeout = setTimeout(flush, wait);\n };\n debounced.clear = ()=>{\n if (typeof timeout === \"number\") {\n clearTimeout(timeout);\n timeout = null;\n flush = null;\n }\n };\n debounced.flush = ()=>{\n flush?.();\n };\n Object.defineProperty(debounced, \"pending\", {\n get: ()=>typeof timeout === \"number\"\n });\n return debounced;\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy9kZWJvdW5jZS50cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUJBLEVBc0JHLEFBdEJIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBc0JHLEFBdEJILEVBc0JHLENBQ0gsRUFBbUMsQUFBbkMsaUNBQW1DO0FBQ25DLE1BQU0sVUFBVSxRQUFRLENBQ3RCLEVBQW9ELEVBQ3BELElBQVksRUFDVSxDQUFDO0lBQ3ZCLEdBQUcsQ0FBQyxPQUFPLEdBQWtCLElBQUk7SUFDakMsR0FBRyxDQUFDLEtBQUssR0FBd0IsSUFBSTtJQUVyQyxLQUFLLENBQUMsU0FBUyxPQUE4QixJQUFJLEdBQWMsQ0FBQztRQUM5RCxTQUFTLENBQUMsS0FBSztRQUNmLEtBQUssT0FBZSxDQUFDO1lBQ25CLFNBQVMsQ0FBQyxLQUFLO1lBQ2YsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEtBQUssSUFBSTtRQUM1QixDQUFDO1FBQ0QsT0FBTyxHQUFHLFVBQVUsQ0FBQyxLQUFLLEVBQUUsSUFBSTtJQUNsQyxDQUFDO0lBRUQsU0FBUyxDQUFDLEtBQUssT0FBZSxDQUFDO1FBQzdCLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTyxLQUFLLENBQVEsU0FBRSxDQUFDO1lBQ2hDLFlBQVksQ0FBQyxPQUFPO1lBQ3BCLE9BQU8sR0FBRyxJQUFJO1lBQ2QsS0FBSyxHQUFHLElBQUk7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVELFNBQVMsQ0FBQyxLQUFLLE9BQWUsQ0FBQztRQUM3QixLQUFLO0lBQ1AsQ0FBQztJQUVELE1BQU0sQ0FBQyxjQUFjLENBQUMsU0FBUyxFQUFFLENBQVMsVUFBRSxDQUFDO1FBQzNDLEdBQUcsTUFBUSxNQUFNLENBQUMsT0FBTyxLQUFLLENBQVE7SUFDeEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxTQUFTO0FBQ2xCLENBQUMifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/std@0.120.0/async/pool.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n\n/**\n * pooledMap transforms values from an (async) iterable into another async\n * iterable. The transforms are done concurrently, with a max concurrency\n * defined by the poolLimit.\n *\n * If an error is thrown from `iterableFn`, no new transformations will begin.\n * All currently executing transformations are allowed to finish and still\n * yielded on success. After that, the rejections among them are gathered and\n * thrown by the iterator in an `AggregateError`.\n *\n * @param poolLimit The maximum count of items being processed concurrently.\n * @param array The input array for mapping.\n * @param iteratorFn The function to call for every item of the array.\n */\nexport function pooledMap(\n poolLimit: number,\n array: Iterable | AsyncIterable,\n iteratorFn: (data: T) => Promise,\n): AsyncIterableIterator {\n // Create the async iterable that is returned from this function.\n const res = new TransformStream, R>({\n async transform(\n p: Promise,\n controller: TransformStreamDefaultController,\n ) {\n controller.enqueue(await p);\n },\n });\n // Start processing items from the iterator\n (async () => {\n const writer = res.writable.getWriter();\n const executing: Array> = [];\n try {\n for await (const item of array) {\n const p = Promise.resolve().then(() => iteratorFn(item));\n // Only write on success. If we `writer.write()` a rejected promise,\n // that will end the iteration. We don't want that yet. Instead let it\n // fail the race, taking us to the catch block where all currently\n // executing jobs are allowed to finish and all rejections among them\n // can be reported together.\n p.then((v) => writer.write(Promise.resolve(v))).catch(() => {});\n const e: Promise = p.then(() =>\n executing.splice(executing.indexOf(e), 1)\n );\n executing.push(e);\n if (executing.length >= poolLimit) {\n await Promise.race(executing);\n }\n }\n // Wait until all ongoing events have processed, then close the writer.\n await Promise.all(executing);\n writer.close();\n } catch {\n const errors = [];\n for (const result of await Promise.allSettled(executing)) {\n if (result.status == \"rejected\") {\n errors.push(result.reason);\n }\n }\n writer.write(Promise.reject(\n new AggregateError(errors, \"Threw while mapping.\"),\n )).catch(() => {});\n }\n })();\n return res.readable[Symbol.asyncIterator]();\n}\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\n/**\n * pooledMap transforms values from an (async) iterable into another async\n * iterable. The transforms are done concurrently, with a max concurrency\n * defined by the poolLimit.\n *\n * If an error is thrown from `iterableFn`, no new transformations will begin.\n * All currently executing transformations are allowed to finish and still\n * yielded on success. After that, the rejections among them are gathered and\n * thrown by the iterator in an `AggregateError`.\n *\n * @param poolLimit The maximum count of items being processed concurrently.\n * @param array The input array for mapping.\n * @param iteratorFn The function to call for every item of the array.\n */ export function pooledMap(poolLimit, array, iteratorFn) {\n // Create the async iterable that is returned from this function.\n const res = new TransformStream({\n async transform (p, controller) {\n controller.enqueue(await p);\n }\n });\n // Start processing items from the iterator\n (async ()=>{\n const writer = res.writable.getWriter();\n const executing = [];\n try {\n for await (const item of array){\n const p = Promise.resolve().then(()=>iteratorFn(item)\n );\n // Only write on success. If we `writer.write()` a rejected promise,\n // that will end the iteration. We don't want that yet. Instead let it\n // fail the race, taking us to the catch block where all currently\n // executing jobs are allowed to finish and all rejections among them\n // can be reported together.\n p.then((v)=>writer.write(Promise.resolve(v))\n ).catch(()=>{\n });\n const e = p.then(()=>executing.splice(executing.indexOf(e), 1)\n );\n executing.push(e);\n if (executing.length >= poolLimit) {\n await Promise.race(executing);\n }\n }\n // Wait until all ongoing events have processed, then close the writer.\n await Promise.all(executing);\n writer.close();\n } catch {\n const errors = [];\n for (const result of (await Promise.allSettled(executing))){\n if (result.status == \"rejected\") {\n errors.push(result.reason);\n }\n }\n writer.write(Promise.reject(new AggregateError(errors, \"Threw while mapping.\"))).catch(()=>{\n });\n }\n })();\n return res.readable[Symbol.asyncIterator]();\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy9wb29sLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQUEwRSxBQUExRSx3RUFBMEU7QUFFMUUsRUFhRyxBQWJIOzs7Ozs7Ozs7Ozs7O0NBYUcsQUFiSCxFQWFHLENBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FDdkIsU0FBaUIsRUFDakIsS0FBcUMsRUFDckMsVUFBbUMsRUFDVCxDQUFDO0lBQzNCLEVBQWlFLEFBQWpFLCtEQUFpRTtJQUNqRSxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQWdCLENBQUM7Y0FDeEMsU0FBUyxFQUNiLENBQWEsRUFDYixVQUErQyxFQUMvQyxDQUFDO1lBQ0QsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQztJQUNELEVBQTJDLEFBQTNDLHlDQUEyQztlQUM5QixDQUFDO1FBQ1osS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFNBQVM7UUFDckMsS0FBSyxDQUFDLFNBQVMsR0FBNEIsQ0FBQyxDQUFDO1FBQzdDLEdBQUcsQ0FBQyxDQUFDO1lBQ0gsR0FBRyxRQUFRLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFFLENBQUM7Z0JBQy9CLEtBQUssQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sR0FBRyxJQUFJLEtBQU8sVUFBVSxDQUFDLElBQUk7O2dCQUN0RCxFQUFvRSxBQUFwRSxrRUFBb0U7Z0JBQ3BFLEVBQXNFLEFBQXRFLG9FQUFzRTtnQkFDdEUsRUFBa0UsQUFBbEUsZ0VBQWtFO2dCQUNsRSxFQUFxRSxBQUFyRSxtRUFBcUU7Z0JBQ3JFLEVBQTRCLEFBQTVCLDBCQUE0QjtnQkFDNUIsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7a0JBQUksS0FBSyxLQUFPLENBQUM7Z0JBQUEsQ0FBQztnQkFDOUQsS0FBSyxDQUFDLENBQUMsR0FBcUIsQ0FBQyxDQUFDLElBQUksS0FDaEMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDOztnQkFFMUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNoQixFQUFFLEVBQUUsU0FBUyxDQUFDLE1BQU0sSUFBSSxTQUFTLEVBQUUsQ0FBQztvQkFDbEMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUztnQkFDOUIsQ0FBQztZQUNILENBQUM7WUFDRCxFQUF1RSxBQUF2RSxxRUFBdUU7WUFDdkUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUztZQUMzQixNQUFNLENBQUMsS0FBSztRQUNkLENBQUMsQ0FBQyxLQUFLLEVBQUMsQ0FBQztZQUNQLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLEdBQUcsRUFBRSxLQUFLLENBQUMsTUFBTSxLQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsR0FBRyxDQUFDO2dCQUN6RCxFQUFFLEVBQUUsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFVLFdBQUUsQ0FBQztvQkFDaEMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTtnQkFDM0IsQ0FBQztZQUNILENBQUM7WUFDRCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQ3pCLEdBQUcsQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQXNCLHlCQUNoRCxLQUFLLEtBQU8sQ0FBQztZQUFBLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsYUFBYTtBQUMxQyxDQUFDIn0=", - "content_type": "application/typescript; charset=utf-8", - "deps": [] - } - }, - "https://deno.land/x/oak_commons@0.1.1/negotiation/language.ts": { - "Source": { - "source": "/*!\n * Adapted directly from negotiator at https://github.com/jshttp/negotiator/\n * which is licensed as follows:\n *\n * (The MIT License)\n *\n * Copyright (c) 2012-2014 Federico Romero\n * Copyright (c) 2012-2014 Isaac Z. Schlueter\n * Copyright (c) 2014-2015 Douglas Christopher Wilson\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\nimport { compareSpecs, isQuality, Specificity } from \"./common.ts\";\n\ninterface LanaguageSpecificity extends Specificity {\n prefix: string;\n suffix?: string;\n full: string;\n}\n\nconst SIMPLE_LANGUAGE_REGEXP = /^\\s*([^\\s\\-;]+)(?:-([^\\s;]+))?\\s*(?:;(.*))?$/;\n\nfunction parseLanguage(\n str: string,\n i: number,\n): LanaguageSpecificity | undefined {\n const match = SIMPLE_LANGUAGE_REGEXP.exec(str);\n if (!match) {\n return undefined;\n }\n\n const [, prefix, suffix] = match;\n const full = suffix ? `${prefix}-${suffix}` : prefix;\n\n let q = 1;\n if (match[3]) {\n const params = match[3].split(\";\");\n for (const param of params) {\n const [key, value] = param.trim().split(\"=\");\n if (key === \"q\") {\n q = parseFloat(value);\n break;\n }\n }\n }\n\n return { prefix, suffix, full, q, i };\n}\n\nfunction parseAcceptLanguage(accept: string): LanaguageSpecificity[] {\n const accepts = accept.split(\",\");\n const result: LanaguageSpecificity[] = [];\n\n for (let i = 0; i < accepts.length; i++) {\n const language = parseLanguage(accepts[i].trim(), i);\n if (language) {\n result.push(language);\n }\n }\n return result;\n}\n\nfunction specify(\n language: string,\n spec: LanaguageSpecificity,\n i: number,\n): Specificity | undefined {\n const p = parseLanguage(language, i);\n if (!p) {\n return undefined;\n }\n let s = 0;\n if (spec.full.toLowerCase() === p.full.toLowerCase()) {\n s |= 4;\n } else if (spec.prefix.toLowerCase() === p.prefix.toLowerCase()) {\n s |= 2;\n } else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) {\n s |= 1;\n } else if (spec.full !== \"*\") {\n return;\n }\n\n return { i, o: spec.i, q: spec.q, s };\n}\n\nfunction getLanguagePriority(\n language: string,\n accepted: LanaguageSpecificity[],\n index: number,\n): Specificity {\n let priority: Specificity = { i: -1, o: -1, q: 0, s: 0 };\n for (const accepts of accepted) {\n const spec = specify(language, accepts, index);\n if (\n spec &&\n ((priority.s ?? 0) - (spec.s ?? 0) || priority.q - spec.q ||\n (priority.o ?? 0) - (spec.o ?? 0)) < 0\n ) {\n priority = spec;\n }\n }\n return priority;\n}\n\nexport function preferredLanguages(\n accept = \"*\",\n provided?: string[],\n): string[] {\n const accepts = parseAcceptLanguage(accept);\n\n if (!provided) {\n return accepts\n .filter(isQuality)\n .sort(compareSpecs)\n .map((spec) => spec.full);\n }\n\n const priorities = provided\n .map((type, index) => getLanguagePriority(type, accepts, index));\n\n return priorities\n .filter(isQuality)\n .sort(compareSpecs)\n .map((priority) => provided[priorities.indexOf(priority)]);\n}\n", - "transpiled": "/*!\n * Adapted directly from negotiator at https://github.com/jshttp/negotiator/\n * which is licensed as follows:\n *\n * (The MIT License)\n *\n * Copyright (c) 2012-2014 Federico Romero\n * Copyright (c) 2012-2014 Isaac Z. Schlueter\n * Copyright (c) 2014-2015 Douglas Christopher Wilson\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */ import { compareSpecs, isQuality } from \"./common.ts\";\nconst SIMPLE_LANGUAGE_REGEXP = /^\\s*([^\\s\\-;]+)(?:-([^\\s;]+))?\\s*(?:;(.*))?$/;\nfunction parseLanguage(str, i) {\n const match = SIMPLE_LANGUAGE_REGEXP.exec(str);\n if (!match) {\n return undefined;\n }\n const [, prefix, suffix] = match;\n const full = suffix ? `${prefix}-${suffix}` : prefix;\n let q = 1;\n if (match[3]) {\n const params = match[3].split(\";\");\n for (const param of params){\n const [key, value] = param.trim().split(\"=\");\n if (key === \"q\") {\n q = parseFloat(value);\n break;\n }\n }\n }\n return {\n prefix,\n suffix,\n full,\n q,\n i\n };\n}\nfunction parseAcceptLanguage(accept) {\n const accepts = accept.split(\",\");\n const result = [];\n for(let i = 0; i < accepts.length; i++){\n const language = parseLanguage(accepts[i].trim(), i);\n if (language) {\n result.push(language);\n }\n }\n return result;\n}\nfunction specify(language, spec, i) {\n const p = parseLanguage(language, i);\n if (!p) {\n return undefined;\n }\n let s = 0;\n if (spec.full.toLowerCase() === p.full.toLowerCase()) {\n s |= 4;\n } else if (spec.prefix.toLowerCase() === p.prefix.toLowerCase()) {\n s |= 2;\n } else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) {\n s |= 1;\n } else if (spec.full !== \"*\") {\n return;\n }\n return {\n i,\n o: spec.i,\n q: spec.q,\n s\n };\n}\nfunction getLanguagePriority(language, accepted, index) {\n let priority = {\n i: -1,\n o: -1,\n q: 0,\n s: 0\n };\n for (const accepts of accepted){\n const spec = specify(language, accepts, index);\n if (spec && ((priority.s ?? 0) - (spec.s ?? 0) || priority.q - spec.q || (priority.o ?? 0) - (spec.o ?? 0)) < 0) {\n priority = spec;\n }\n }\n return priority;\n}\nexport function preferredLanguages(accept = \"*\", provided) {\n const accepts = parseAcceptLanguage(accept);\n if (!provided) {\n return accepts.filter(isQuality).sort(compareSpecs).map((spec)=>spec.full\n );\n }\n const priorities = provided.map((type, index)=>getLanguagePriority(type, accepts, index)\n );\n return priorities.filter(isQuality).sort(compareSpecs).map((priority)=>provided[priorities.indexOf(priority)]\n );\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC94L29ha19jb21tb25zQDAuMS4xL25lZ290aWF0aW9uL2xhbmd1YWdlLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQTRCRyxBQTVCSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQTRCRyxBQTVCSCxFQTRCRyxDQUVILE1BQU0sR0FBRyxZQUFZLEVBQUUsU0FBUyxRQUFxQixDQUFhO0FBUWxFLEtBQUssQ0FBQyxzQkFBc0I7U0FFbkIsYUFBYSxDQUNwQixHQUFXLEVBQ1gsQ0FBUyxFQUN5QixDQUFDO0lBQ25DLEtBQUssQ0FBQyxLQUFLLEdBQUcsc0JBQXNCLENBQUMsSUFBSSxDQUFDLEdBQUc7SUFDN0MsRUFBRSxHQUFHLEtBQUssRUFBRSxDQUFDO1FBQ1gsTUFBTSxDQUFDLFNBQVM7SUFDbEIsQ0FBQztJQUVELEtBQUssSUFBSSxNQUFNLEVBQUUsTUFBTSxJQUFJLEtBQUs7SUFDaEMsS0FBSyxDQUFDLElBQUksR0FBRyxNQUFNLE1BQU0sTUFBTSxDQUFDLENBQUMsRUFBRSxNQUFNLEtBQUssTUFBTTtJQUVwRCxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDVCxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ2IsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFHO1FBQ2pDLEdBQUcsRUFBRSxLQUFLLENBQUMsS0FBSyxJQUFJLE1BQU0sQ0FBRSxDQUFDO1lBQzNCLEtBQUssRUFBRSxHQUFHLEVBQUUsS0FBSyxJQUFJLEtBQUssQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUc7WUFDM0MsRUFBRSxFQUFFLEdBQUcsS0FBSyxDQUFHLElBQUUsQ0FBQztnQkFDaEIsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxLQUFLO2dCQUNwQixLQUFLO1lBQ1AsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLENBQUM7UUFB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", - "content_type": "application/typescript; charset=utf-8", - "deps": ["https://deno.land/x/oak_commons@0.1.1/negotiation/common.ts"] - } - }, - "file:///src/worker/registry_config.ts": { - "Source": { - "source": "/* Copyright 2021 the Deno authors. All rights reserved. MIT license. */\n\nimport { accepts } from \"https://deno.land/x/oak_commons@0.1.1/negotiation.ts\";\n\ninterface RegistryDefVariable {\n key: string;\n documentation?: string;\n url: string;\n}\n\ninterface RegistryDef {\n schema: string;\n variables: RegistryDefVariable[];\n}\n\ninterface RegistryConfig {\n version: 1 | 2;\n registries: RegistryDef[];\n}\n\nconst MAX_AGE_1_DAY = \"max-age=86400\";\n\n/** The _legacy_ v1 configuration file. This will be provided to any client\n * which does not indicate it is capable of understanding the v2 registry\n * (earlier than Deno 1.17.1) */\nconst configV1: RegistryConfig = {\n version: 1,\n registries: [\n {\n schema: \"/x/:module([a-z0-9_]*)@:version?/:path*\",\n variables: [\n {\n key: \"module\",\n url: \"https://api.deno.land/modules?simple=1\",\n },\n {\n key: \"version\",\n url: \"https://deno.land/_vsc1/modules/${module}\",\n },\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/${module}/v/${{version}}\",\n },\n ],\n },\n {\n schema: \"/x/:module([a-z0-9_]*)/:path*\",\n variables: [\n {\n key: \"module\",\n url: \"https://api.deno.land/modules?simple=1\",\n },\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/${module}/v_latest\",\n },\n ],\n },\n {\n schema: \"/std@:version?/:path*\",\n variables: [\n {\n key: \"version\",\n url: \"https://deno.land/_vsc1/modules/std\",\n },\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/std/v/${{version}}\",\n },\n ],\n },\n {\n schema: \"/std/:path*\",\n variables: [\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/std/v_latest\",\n },\n ],\n },\n ],\n};\n\n/** This is the v2 registry configuration which provides documentation\n * endpoints and allows incremental completion/search of variables. */\nconst configV2: RegistryConfig = {\n version: 2,\n registries: [\n {\n schema: \"/x/:module([a-z0-9_]+)@:version?/:path*\",\n variables: [\n {\n key: \"module\",\n documentation: \"/_api/details/x/${module}\",\n url: \"/_api/x/${module}\",\n },\n {\n key: \"version\",\n documentation: \"/_api/details/x/${module}/${{version}}\",\n url: \"/_api/x/${module}/${{version}}\",\n },\n {\n key: \"path\",\n documentation: \"/_api/details/x/${module}/${{version}}/${path}\",\n url: \"/_api/x/${module}/${{version}}/${path}\",\n },\n ],\n },\n {\n schema: \"/x/:module([a-z0-9_]*)/:path*\",\n variables: [\n {\n key: \"module\",\n documentation: \"/_api/details/x/${module}\",\n url: \"/_api/x/${module}\",\n },\n {\n key: \"path\",\n documentation: \"/_api/details/x/${module}/_latest/${path}\",\n url: \"/_api/x/${module}/_latest/${path}\",\n },\n ],\n },\n {\n schema: \"/std@:version?/:path*\",\n variables: [\n {\n key: \"version\",\n documentation: \"/_api/details/std/${{version}}\",\n url: \"/_api/x/std/${{version}}\",\n },\n {\n key: \"path\",\n documentation: \"/_api/details/std/${{version}}/${path}\",\n url: \"/_api/x/std/${{version}}/${path}\",\n },\n ],\n },\n {\n schema: \"/std/:path*\",\n variables: [\n {\n key: \"path\",\n documentation: \"/_api/details/std/_latest/${path}\",\n url: \"/_api/x/std/_latest/${path}\",\n },\n ],\n },\n ],\n};\n\n/** Provide the v1 or v2 registry configuration based on the accepts header\n * provided by the client. Deno 1.17.1 and later indicates it accepts a\n * configuration of v2. */\nexport function handleConfigRequest(request: Request): Promise {\n let body: unknown;\n let contentType = \"application/json\";\n const accept = request.headers.get(\"accept\");\n if (\n accept !== null && accept !== \"*/*\" &&\n accepts(request, \"application/vnd.deno.reg.v2+json\")\n ) {\n contentType = \"application/vnd.deno.reg.v2+json\";\n body = configV2;\n } else {\n body = configV1;\n }\n return Promise.resolve(\n new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_DAY,\n \"content-type\": contentType,\n },\n }),\n );\n}\n", - "transpiled": "/* Copyright 2021 the Deno authors. All rights reserved. MIT license. */ import { accepts } from \"https://deno.land/x/oak_commons@0.1.1/negotiation.ts\";\nconst MAX_AGE_1_DAY = \"max-age=86400\";\n/** The _legacy_ v1 configuration file. This will be provided to any client\n * which does not indicate it is capable of understanding the v2 registry\n * (earlier than Deno 1.17.1) */ const configV1 = {\n version: 1,\n registries: [\n {\n schema: \"/x/:module([a-z0-9_]*)@:version?/:path*\",\n variables: [\n {\n key: \"module\",\n url: \"https://api.deno.land/modules?simple=1\"\n },\n {\n key: \"version\",\n url: \"https://deno.land/_vsc1/modules/${module}\"\n },\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/${module}/v/${{version}}\"\n }, \n ]\n },\n {\n schema: \"/x/:module([a-z0-9_]*)/:path*\",\n variables: [\n {\n key: \"module\",\n url: \"https://api.deno.land/modules?simple=1\"\n },\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/${module}/v_latest\"\n }, \n ]\n },\n {\n schema: \"/std@:version?/:path*\",\n variables: [\n {\n key: \"version\",\n url: \"https://deno.land/_vsc1/modules/std\"\n },\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/std/v/${{version}}\"\n }, \n ]\n },\n {\n schema: \"/std/:path*\",\n variables: [\n {\n key: \"path\",\n url: \"https://deno.land/_vsc1/modules/std/v_latest\"\n }, \n ]\n }, \n ]\n};\n/** This is the v2 registry configuration which provides documentation\n * endpoints and allows incremental completion/search of variables. */ const configV2 = {\n version: 2,\n registries: [\n {\n schema: \"/x/:module([a-z0-9_]+)@:version?/:path*\",\n variables: [\n {\n key: \"module\",\n documentation: \"/_api/details/x/${module}\",\n url: \"/_api/x/${module}\"\n },\n {\n key: \"version\",\n documentation: \"/_api/details/x/${module}/${{version}}\",\n url: \"/_api/x/${module}/${{version}}\"\n },\n {\n key: \"path\",\n documentation: \"/_api/details/x/${module}/${{version}}/${path}\",\n url: \"/_api/x/${module}/${{version}}/${path}\"\n }, \n ]\n },\n {\n schema: \"/x/:module([a-z0-9_]*)/:path*\",\n variables: [\n {\n key: \"module\",\n documentation: \"/_api/details/x/${module}\",\n url: \"/_api/x/${module}\"\n },\n {\n key: \"path\",\n documentation: \"/_api/details/x/${module}/_latest/${path}\",\n url: \"/_api/x/${module}/_latest/${path}\"\n }, \n ]\n },\n {\n schema: \"/std@:version?/:path*\",\n variables: [\n {\n key: \"version\",\n documentation: \"/_api/details/std/${{version}}\",\n url: \"/_api/x/std/${{version}}\"\n },\n {\n key: \"path\",\n documentation: \"/_api/details/std/${{version}}/${path}\",\n url: \"/_api/x/std/${{version}}/${path}\"\n }, \n ]\n },\n {\n schema: \"/std/:path*\",\n variables: [\n {\n key: \"path\",\n documentation: \"/_api/details/std/_latest/${path}\",\n url: \"/_api/x/std/_latest/${path}\"\n }, \n ]\n }, \n ]\n};\n/** Provide the v1 or v2 registry configuration based on the accepts header\n * provided by the client. Deno 1.17.1 and later indicates it accepts a\n * configuration of v2. */ export function handleConfigRequest(request) {\n let body;\n let contentType = \"application/json\";\n const accept = request.headers.get(\"accept\");\n if (accept !== null && accept !== \"*/*\" && accepts(request, \"application/vnd.deno.reg.v2+json\")) {\n contentType = \"application/vnd.deno.reg.v2+json\";\n body = configV2;\n } else {\n body = configV1;\n }\n return Promise.resolve(new Response(JSON.stringify(body), {\n headers: {\n \"cache-control\": MAX_AGE_1_DAY,\n \"content-type\": contentType\n }\n }));\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxmaWxlOi8vL3NyYy93b3JrZXIvcmVnaXN0cnlfY29uZmlnLnRzPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxFQUF3RSxBQUF4RSxvRUFBd0UsQUFBeEUsRUFBd0UsQ0FFeEUsTUFBTSxHQUFHLE9BQU8sUUFBUSxDQUFzRDtBQWtCOUUsS0FBSyxDQUFDLGFBQWEsR0FBRyxDQUFlO0FBRXJDLEVBRWdDLEFBRmhDOzs4QkFFZ0MsQUFGaEMsRUFFZ0MsQ0FDaEMsS0FBSyxDQUFDLFFBQVEsR0FBbUIsQ0FBQztJQUNoQyxPQUFPLEVBQUUsQ0FBQztJQUNWLFVBQVUsRUFBRSxDQUFDO1FBQ1gsQ0FBQztZQUNDLE1BQU0sRUFBRSxDQUF5QztZQUNqRCxTQUFTLEVBQUUsQ0FBQztnQkFDVixDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFRO29CQUNiLEdBQUcsRUFBRSxDQUF3QztnQkFDL0MsQ0FBQztnQkFDRCxDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFTO29CQUNkLEdBQUcsRUFBRSxDQUEyQztnQkFDbEQsQ0FBQztnQkFDRCxDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFNO29CQUNYLEdBQUcsRUFBRSxDQUEwRDtnQkFDakUsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsQ0FBQztZQUNDLE1BQU0sRUFBRSxDQUErQjtZQUN2QyxTQUFTLEVBQUUsQ0FBQztnQkFDVixDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFRO29CQUNiLEdBQUcsRUFBRSxDQUF3QztnQkFDL0MsQ0FBQztnQkFDRCxDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFNO29CQUNYLEdBQUcsRUFBRSxDQUFvRDtnQkFDM0QsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsQ0FBQztZQUNDLE1BQU0sRUFBRSxDQUF1QjtZQUMvQixTQUFTLEVBQUUsQ0FBQztnQkFDVixDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFTO29CQUNkLEdBQUcsRUFBRSxDQUFxQztnQkFDNUMsQ0FBQztnQkFDRCxDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFNO29CQUNYLEdBQUcsRUFBRSxDQUFvRDtnQkFDM0QsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsQ0FBQztZQUNDLE1BQU0sRUFBRSxDQUFhO1lBQ3JCLFNBQVMsRUFBRSxDQUFDO2dCQUNWLENBQUM7b0JBQ0MsR0FBRyxFQUFFLENBQU07b0JBQ1gsR0FBRyxFQUFFLENBQThDO2dCQUNyRCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVELEVBQ3NFLEFBRHRFO29FQUNzRSxBQUR0RSxFQUNzRSxDQUN0RSxLQUFLLENBQUMsUUFBUSxHQUFtQixDQUFDO0lBQ2hDLE9BQU8sRUFBRSxDQUFDO0lBQ1YsVUFBVSxFQUFFLENBQUM7UUFDWCxDQUFDO1lBQ0MsTUFBTSxFQUFFLENBQXlDO1lBQ2pELFNBQVMsRUFBRSxDQUFDO2dCQUNWLENBQUM7b0JBQ0MsR0FBRyxFQUFFLENBQVE7b0JBQ2IsYUFBYSxFQUFFLENBQTJCO29CQUMxQyxHQUFHLEVBQUUsQ0FBbUI7Z0JBQzFCLENBQUM7Z0JBQ0QsQ0FBQztvQkFDQyxHQUFHLEVBQUUsQ0FBUztvQkFDZCxhQUFhLEVBQUUsQ0FBd0M7b0JBQ3ZELEdBQUcsRUFBRSxDQUFnQztnQkFDdkMsQ0FBQztnQkFDRCxDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFNO29CQUNYLGFBQWEsRUFBRSxDQUFnRDtvQkFDL0QsR0FBRyxFQUFFLENBQXdDO2dCQUMvQyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFDRCxDQUFDO1lBQ0MsTUFBTSxFQUFFLENBQStCO1lBQ3ZDLFNBQVMsRUFBRSxDQUFDO2dCQUNWLENBQUM7b0JBQ0MsR0FBRyxFQUFFLENBQVE7b0JBQ2IsYUFBYSxFQUFFLENBQTJCO29CQUMxQyxHQUFHLEVBQUUsQ0FBbUI7Z0JBQzFCLENBQUM7Z0JBQ0QsQ0FBQztvQkFDQyxHQUFHLEVBQUUsQ0FBTTtvQkFDWCxhQUFhLEVBQUUsQ0FBMkM7b0JBQzFELEdBQUcsRUFBRSxDQUFtQztnQkFDMUMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsQ0FBQztZQUNDLE1BQU0sRUFBRSxDQUF1QjtZQUMvQixTQUFTLEVBQUUsQ0FBQztnQkFDVixDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFTO29CQUNkLGFBQWEsRUFBRSxDQUFnQztvQkFDL0MsR0FBRyxFQUFFLENBQTBCO2dCQUNqQyxDQUFDO2dCQUNELENBQUM7b0JBQ0MsR0FBRyxFQUFFLENBQU07b0JBQ1gsYUFBYSxFQUFFLENBQXdDO29CQUN2RCxHQUFHLEVBQUUsQ0FBa0M7Z0JBQ3pDLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELENBQUM7WUFDQyxNQUFNLEVBQUUsQ0FBYTtZQUNyQixTQUFTLEVBQUUsQ0FBQztnQkFDVixDQUFDO29CQUNDLEdBQUcsRUFBRSxDQUFNO29CQUNYLGFBQWEsRUFBRSxDQUFtQztvQkFDbEQsR0FBRyxFQUFFLENBQTZCO2dCQUNwQyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVELEVBRTBCLEFBRjFCOzt3QkFFMEIsQUFGMUIsRUFFMEIsQ0FDMUIsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE9BQWdCLEVBQXFCLENBQUM7SUFDeEUsR0FBRyxDQUFDLElBQUk7SUFDUixHQUFHLENBQUMsV0FBVyxHQUFHLENBQWtCO0lBQ3BDLEtBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBUTtJQUMzQyxFQUFFLEVBQ0EsTUFBTSxLQUFLLElBQUksSUFBSSxNQUFNLEtBQUssQ0FBSyxRQUNuQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQWtDLG9DQUNuRCxDQUFDO1FBQ0QsV0FBVyxHQUFHLENBQWtDO1FBQ2hELElBQUksR0FBRyxRQUFRO0lBQ2pCLENBQUMsTUFBTSxDQUFDO1FBQ04sSUFBSSxHQUFHLFFBQVE7SUFDakIsQ0FBQztJQUNELE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUNwQixHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxHQUFHLENBQUM7UUFDbEMsT0FBTyxFQUFFLENBQUM7WUFDUixDQUFlLGdCQUFFLGFBQWE7WUFDOUIsQ0FBYyxlQUFFLFdBQVc7UUFDN0IsQ0FBQztJQUNILENBQUM7QUFFTCxDQUFDIn0=", - "content_type": null, - "deps": ["https://deno.land/x/oak_commons@0.1.1/negotiation.ts"] - } - }, - "https://deno.land/std@0.120.0/async/mod.ts": { - "Source": { - "source": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nexport * from \"./debounce.ts\";\nexport * from \"./deferred.ts\";\nexport * from \"./delay.ts\";\nexport * from \"./mux_async_iterator.ts\";\nexport * from \"./pool.ts\";\nexport * from \"./tee.ts\";\nexport * from \"./deadline.ts\";\n", - "transpiled": "// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.\nexport * from \"./debounce.ts\";\nexport * from \"./deferred.ts\";\nexport * from \"./delay.ts\";\nexport * from \"./mux_async_iterator.ts\";\nexport * from \"./pool.ts\";\nexport * from \"./tee.ts\";\nexport * from \"./deadline.ts\";\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2Rlbm8ubGFuZC9zdGRAMC4xMjAuMC9hc3luYy9tb2QudHM+Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEVBQTBFLEFBQTFFLHdFQUEwRTtjQUM1RCxDQUFlO2NBQ2YsQ0FBZTtjQUNmLENBQVk7Y0FDWixDQUF5QjtjQUN6QixDQUFXO2NBQ1gsQ0FBVTtjQUNWLENBQWUifQ==", - "content_type": "application/typescript; charset=utf-8", - "deps": [ - "https://deno.land/std@0.120.0/async/debounce.ts", - "https://deno.land/std@0.120.0/async/deferred.ts", - "https://deno.land/std@0.120.0/async/delay.ts", - "https://deno.land/std@0.120.0/async/mux_async_iterator.ts", - "https://deno.land/std@0.120.0/async/pool.ts", - "https://deno.land/std@0.120.0/async/tee.ts", - "https://deno.land/std@0.120.0/async/deadline.ts" - ] - } - } - } -} diff --git a/src/testdata/emit/b.ts b/src/testdata/emit/b.ts deleted file mode 100644 index 59d1689..0000000 --- a/src/testdata/emit/b.ts +++ /dev/null @@ -1 +0,0 @@ -export const b = "b"; diff --git a/src/testdata/emit/b.ts.map b/src/testdata/emit/b.ts.map deleted file mode 100644 index bfbaadc..0000000 --- a/src/testdata/emit/b.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["file:///b.ts"],"sourcesContent":["export const b = \"b\";\n"],"names":[],"mappings":"AAAA,OAAO,MAAM,IAAI,IAAI"} \ No newline at end of file diff --git a/src/testdata/emit/data.json b/src/testdata/emit/data.json deleted file mode 100644 index 81c545e..0000000 --- a/src/testdata/emit/data.json +++ /dev/null @@ -1 +0,0 @@ -1234 diff --git a/src/testdata/emit/dynamic.ts b/src/testdata/emit/dynamic.ts deleted file mode 100644 index 769565a..0000000 --- a/src/testdata/emit/dynamic.ts +++ /dev/null @@ -1,7 +0,0 @@ -const { default: data } = await import("./data.json", { - assert: { - type: "json" - } -}); -await import("./relative_doesnt_exist.ts"); -await import("not_real"); diff --git a/src/testdata/emit/dynamic_data.ts b/src/testdata/emit/dynamic_data.ts deleted file mode 100644 index 775cf27..0000000 --- a/src/testdata/emit/dynamic_data.ts +++ /dev/null @@ -1 +0,0 @@ -const { Nani } = await import("data:application/javascript,export const Nani = '何'"); diff --git a/src/testdata/emit/json.ts b/src/testdata/emit/json.ts deleted file mode 100644 index 411bc50..0000000 --- a/src/testdata/emit/json.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as data } from "./data.json" with { - type: "json" -}; diff --git a/src/testdata/emit/main.ts b/src/testdata/emit/main.ts deleted file mode 100644 index 87e6100..0000000 --- a/src/testdata/emit/main.ts +++ /dev/null @@ -1 +0,0 @@ -export * as a from "./a.ts"; diff --git a/src/testdata/emit/main.ts.map b/src/testdata/emit/main.ts.map deleted file mode 100644 index 8f68dcb..0000000 --- a/src/testdata/emit/main.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["file:///main.ts"],"sourcesContent":["export * as a from \"./a.ts\";\n"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS"} \ No newline at end of file diff --git a/src/testdata/json.eszip2 b/src/testdata/json.eszip2 deleted file mode 100644 index c2f73ef..0000000 Binary files a/src/testdata/json.eszip2 and /dev/null differ diff --git a/src/testdata/no_npm_packages.eszip2_1 b/src/testdata/no_npm_packages.eszip2_1 deleted file mode 100644 index ae33ee9..0000000 Binary files a/src/testdata/no_npm_packages.eszip2_1 and /dev/null differ diff --git a/src/testdata/npm_packages.eszip2_1 b/src/testdata/npm_packages.eszip2_1 deleted file mode 100644 index c2d3cf2..0000000 Binary files a/src/testdata/npm_packages.eszip2_1 and /dev/null differ diff --git a/src/testdata/npm_packages_invalid_1.eszip2_1 b/src/testdata/npm_packages_invalid_1.eszip2_1 deleted file mode 100644 index a608dd8..0000000 Binary files a/src/testdata/npm_packages_invalid_1.eszip2_1 and /dev/null differ diff --git a/src/testdata/redirect.eszip2 b/src/testdata/redirect.eszip2 deleted file mode 100644 index b661e21..0000000 Binary files a/src/testdata/redirect.eszip2 and /dev/null differ diff --git a/src/testdata/redirect_data/b.ts b/src/testdata/redirect_data/b.ts deleted file mode 100644 index 59d1689..0000000 --- a/src/testdata/redirect_data/b.ts +++ /dev/null @@ -1 +0,0 @@ -export const b = "b"; diff --git a/src/testdata/redirect_data/b.ts.map b/src/testdata/redirect_data/b.ts.map deleted file mode 100644 index 933fec3..0000000 --- a/src/testdata/redirect_data/b.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["file:///b.ts"],"sourcesContent":["export const b = \"b\";\n"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAG"} \ No newline at end of file diff --git a/src/testdata/redirect_data/main.ts b/src/testdata/redirect_data/main.ts deleted file mode 100644 index 87e6100..0000000 --- a/src/testdata/redirect_data/main.ts +++ /dev/null @@ -1 +0,0 @@ -export * as a from "./a.ts"; diff --git a/src/testdata/redirect_data/main.ts.map b/src/testdata/redirect_data/main.ts.map deleted file mode 100644 index aa771a4..0000000 --- a/src/testdata/redirect_data/main.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["file:///main.ts"],"sourcesContent":["export * as a from \"./a.ts\";\n"],"names":[],"mappings":"AAAA,MAAM,MAAM,CAAC,MAAM,CAAQ"} \ No newline at end of file diff --git a/src/testdata/source/a.ts b/src/testdata/source/a.ts deleted file mode 120000 index b47a87d..0000000 --- a/src/testdata/source/a.ts +++ /dev/null @@ -1 +0,0 @@ -b.ts \ No newline at end of file diff --git a/src/testdata/source/b.ts b/src/testdata/source/b.ts deleted file mode 100644 index 59d1689..0000000 --- a/src/testdata/source/b.ts +++ /dev/null @@ -1 +0,0 @@ -export const b = "b"; diff --git a/src/testdata/source/child1.ts b/src/testdata/source/child1.ts deleted file mode 100644 index de4609f..0000000 --- a/src/testdata/source/child1.ts +++ /dev/null @@ -1 +0,0 @@ -import "./grandchild1.ts"; \ No newline at end of file diff --git a/src/testdata/source/child2.ts b/src/testdata/source/child2.ts deleted file mode 100644 index 6164c25..0000000 --- a/src/testdata/source/child2.ts +++ /dev/null @@ -1 +0,0 @@ -import "./grandchild2.ts"; \ No newline at end of file diff --git a/src/testdata/source/data.json b/src/testdata/source/data.json deleted file mode 100644 index 81c545e..0000000 --- a/src/testdata/source/data.json +++ /dev/null @@ -1 +0,0 @@ -1234 diff --git a/src/testdata/source/dynamic.ts b/src/testdata/source/dynamic.ts deleted file mode 100644 index 9e8c30c..0000000 --- a/src/testdata/source/dynamic.ts +++ /dev/null @@ -1,5 +0,0 @@ -const { default: data } = await import("./data.json", { - assert: { type: "json" }, -}); -await import("./relative_doesnt_exist.ts"); -await import("not_real"); \ No newline at end of file diff --git a/src/testdata/source/dynamic_data.ts b/src/testdata/source/dynamic_data.ts deleted file mode 100644 index 0a9ad6f..0000000 --- a/src/testdata/source/dynamic_data.ts +++ /dev/null @@ -1 +0,0 @@ -const {Nani} = await import("data:application/javascript,export const Nani = '何'"); \ No newline at end of file diff --git a/src/testdata/source/external.ts b/src/testdata/source/external.ts deleted file mode 100644 index e704d30..0000000 --- a/src/testdata/source/external.ts +++ /dev/null @@ -1 +0,0 @@ -export * as fs from "extern:fs"; \ No newline at end of file diff --git a/src/testdata/source/grandchild1.ts b/src/testdata/source/grandchild1.ts deleted file mode 100644 index 7c7eeb4..0000000 --- a/src/testdata/source/grandchild1.ts +++ /dev/null @@ -1 +0,0 @@ -export const grandchild1 = "grandchild1"; \ No newline at end of file diff --git a/src/testdata/source/grandchild2.ts b/src/testdata/source/grandchild2.ts deleted file mode 100644 index 8d02849..0000000 --- a/src/testdata/source/grandchild2.ts +++ /dev/null @@ -1,2 +0,0 @@ - -export const grandchild2 = "grandchild2"; \ No newline at end of file diff --git a/src/testdata/source/import_import_map.js b/src/testdata/source/import_import_map.js deleted file mode 100644 index 0c6d049..0000000 --- a/src/testdata/source/import_import_map.js +++ /dev/null @@ -1 +0,0 @@ -import m from "./import_map.json" assert { type: "json" }; diff --git a/src/testdata/source/import_map.json b/src/testdata/source/import_map.json deleted file mode 100644 index c7dd2b2..0000000 --- a/src/testdata/source/import_map.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "imports": { - "a": "./a.ts" - } -} diff --git a/src/testdata/source/json.ts b/src/testdata/source/json.ts deleted file mode 100644 index aa8f858..0000000 --- a/src/testdata/source/json.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as data } from "./data.json" assert { - type: "json" -}; diff --git a/src/testdata/source/main.ts b/src/testdata/source/main.ts deleted file mode 100644 index 87e6100..0000000 --- a/src/testdata/source/main.ts +++ /dev/null @@ -1 +0,0 @@ -export * as a from "./a.ts"; diff --git a/src/testdata/source/mapped.js b/src/testdata/source/mapped.js deleted file mode 100644 index a5a084f..0000000 --- a/src/testdata/source/mapped.js +++ /dev/null @@ -1 +0,0 @@ -import "a"; diff --git a/src/testdata/source/math.wasm b/src/testdata/source/math.wasm deleted file mode 100644 index 6b3950f..0000000 Binary files a/src/testdata/source/math.wasm and /dev/null differ diff --git a/src/testdata/source/npm_imports_main.ts b/src/testdata/source/npm_imports_main.ts deleted file mode 100644 index 14fce05..0000000 --- a/src/testdata/source/npm_imports_main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import "npm:d/foo"; -import "./npm_imports_submodule.ts"; -import "npm:other"; -import "npm:a@^1.2/foo"; \ No newline at end of file diff --git a/src/testdata/source/npm_imports_submodule.ts b/src/testdata/source/npm_imports_submodule.ts deleted file mode 100644 index de83ebd..0000000 --- a/src/testdata/source/npm_imports_submodule.ts +++ /dev/null @@ -1,2 +0,0 @@ -import "npm:a@^1.2/bar"; -import "npm:other/bar"; diff --git a/src/testdata/source/parent.ts b/src/testdata/source/parent.ts deleted file mode 100644 index 8eb7e57..0000000 --- a/src/testdata/source/parent.ts +++ /dev/null @@ -1,2 +0,0 @@ -import "./child1.ts"; -import "./child2.ts"; \ No newline at end of file diff --git a/src/testdata/source/wasm.ts b/src/testdata/source/wasm.ts deleted file mode 100644 index 009f1ae..0000000 --- a/src/testdata/source/wasm.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { add } from "./math.wasm"; -console.log(add(1, 2)); diff --git a/src/testdata/wasm.eszip2_3 b/src/testdata/wasm.eszip2_3 deleted file mode 100644 index d8e948f..0000000 Binary files a/src/testdata/wasm.eszip2_3 and /dev/null differ diff --git a/src/v1.rs b/src/v1.rs deleted file mode 100644 index f969b62..0000000 --- a/src/v1.rs +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::collections::HashMap; -use std::collections::HashSet; -use std::sync::Arc; -use std::sync::Mutex; - -use serde::Deserialize; -use serde::Serialize; -use url::Url; - -use crate::Module; -use crate::ModuleInner; -use crate::ModuleKind; -use crate::ParseError; - -const ESZIP_V1_GRAPH_VERSION: u32 = 1; - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct EszipV1 { - version: u32, - modules: Arc>>, -} - -impl EszipV1 { - pub fn from_modules(modules: HashMap) -> Self { - Self { - version: ESZIP_V1_GRAPH_VERSION, - modules: Arc::new(Mutex::new(modules)), - } - } - - pub fn parse(data: &[u8]) -> Result { - let eszip: EszipV1 = - serde_json::from_slice(data).map_err(ParseError::InvalidV1Json)?; - if eszip.version != ESZIP_V1_GRAPH_VERSION { - return Err(ParseError::InvalidV1Version(eszip.version)); - } - Ok(eszip) - } - - pub fn into_bytes(self) -> Vec { - serde_json::to_vec(&self).unwrap() - } - - pub fn get_module(&self, specifier: &str) -> Option { - let mut specifier = &Url::parse(specifier).ok()?; - let mut visited = HashSet::new(); - let modules = self.modules.lock().unwrap(); - loop { - visited.insert(specifier); - let module = modules.get(specifier)?; - match module { - ModuleInfo::Redirect(redirect) => { - specifier = redirect; - if visited.contains(specifier) { - return None; - } - } - ModuleInfo::Source(..) => { - let module = Module { - specifier: specifier.to_string(), - kind: ModuleKind::JavaScript, - inner: ModuleInner::V1(EszipV1 { - version: self.version, - modules: self.modules.clone(), - }), - }; - return Some(module); - } - } - } - } - - pub fn get_import_map(&self, _specifier: &str) -> Option { - // V1 never contains an import map in it. This method exists to make it - // consistent with V2's interface. - None - } - - /// Get source code of the module. - pub(crate) fn get_module_source(&self, specifier: &str) -> Option> { - let specifier = &Url::parse(specifier).ok()?; - let modules = self.modules.lock().unwrap(); - let module = modules.get(specifier).unwrap(); - match module { - ModuleInfo::Redirect(_) => panic!("Redirects should be resolved"), - ModuleInfo::Source(module) => { - let source = module.transpiled.as_ref().unwrap_or(&module.source); - Some(source.clone().into()) - } - } - } - - /// Removes the module from the modules map and returns the source code. - pub(crate) fn take(&self, specifier: &str) -> Option> { - let specifier = &Url::parse(specifier).ok()?; - let mut modules = self.modules.lock().unwrap(); - // Note: we don't have a need to preserve the module in the map for v1, so we can - // remove the module from the map. In v2, we need to preserve the module in the map - // to be able to get source map for the module. - let module = modules.remove(specifier)?; - match module { - ModuleInfo::Redirect(_) => panic!("Redirects should be resolved"), - ModuleInfo::Source(module_source) => { - let source = module_source.transpiled.unwrap_or(module_source.source); - Some(source.into()) - } - } - } - - fn specifiers(&self) -> Vec { - let modules = self.modules.lock().unwrap(); - modules.keys().cloned().collect() - } -} - -/// Get an iterator over all the modules in this eszip archive. -/// -/// Note that the iterator will iterate over the specifiers' "snapshot" of the -/// archive. If a new module is added to the archive after the iterator is -/// created via `into_iter()`, that module will not be iterated over. -impl IntoIterator for EszipV1 { - type Item = (String, Module); - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - let specifiers = self.specifiers(); - let mut v = Vec::with_capacity(specifiers.len()); - for specifier in specifiers { - let Some(module) = self.get_module(specifier.as_str()) else { - continue; - }; - v.push((specifier.to_string(), module)); - } - - v.into_iter() - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum ModuleInfo { - Redirect(Url), - Source(ModuleSource), -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ModuleSource { - pub source: Arc, - pub transpiled: Option>, - pub content_type: Option, - pub deps: Vec, -} - -#[cfg(test)] -mod tests { - use super::*; - use pretty_assertions::assert_eq; - - #[test] - fn file_format_parse() { - let data = include_bytes!("./testdata/basic.json"); - let eszip = EszipV1::parse(data).unwrap(); - assert_eq!(eszip.version, 1); - assert_eq!(eszip.modules.lock().unwrap().len(), 1); - let specifier = "https://gist.githubusercontent.com/lucacasonato/f3e21405322259ca4ed155722390fda2/raw/e25acb49b681e8e1da5a2a33744b7a36d538712d/hello.js"; - let module = eszip.get_module(specifier).unwrap(); - assert_eq!(module.specifier, specifier); - let inner = module.inner; - let bytes = match inner { - crate::ModuleInner::V1(eszip) => { - eszip.get_module_source(specifier).unwrap() - } - crate::ModuleInner::V2(_) => unreachable!(), - }; - assert_eq!(&*bytes, b"addEventListener(\"fetch\", (event)=>{\n event.respondWith(new Response(\"Hello World\", {\n headers: {\n \"content-type\": \"text/plain\"\n }\n }));\n});\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxodHRwczovL2dpc3QuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2x1Y2FjYXNvbmF0by9mM2UyMTQwNTMyMjI1OWNhNGVkMTU1NzIyMzkwZmRhMi9yYXcvZTI1YWNiNDliNjgxZThlMWRhNWEyYTMzNzQ0YjdhMzZkNTM4NzEyZC9oZWxsby5qcz4iXSwic291cmNlc0NvbnRlbnQiOlsiYWRkRXZlbnRMaXN0ZW5lcihcImZldGNoXCIsIChldmVudCkgPT4ge1xuICBldmVudC5yZXNwb25kV2l0aChuZXcgUmVzcG9uc2UoXCJIZWxsbyBXb3JsZFwiLCB7XG4gICAgaGVhZGVyczogeyBcImNvbnRlbnQtdHlwZVwiOiBcInRleHQvcGxhaW5cIiB9LFxuICB9KSk7XG59KTsiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZ0JBQUEsRUFBQSxLQUFBLElBQUEsS0FBQTtBQUNBLFNBQUEsQ0FBQSxXQUFBLEtBQUEsUUFBQSxFQUFBLFdBQUE7QUFDQSxlQUFBO2FBQUEsWUFBQSxJQUFBLFVBQUEifQ=="); - } - - #[tokio::test] - async fn get_transpiled_for_ts() { - let data = include_bytes!("./testdata/dotland.json"); - let eszip = EszipV1::parse(data).unwrap(); - assert_eq!(eszip.version, 1); - - let module = eszip.get_module("file:///src/worker/handler.ts").unwrap(); - assert_eq!(module.specifier, "file:///src/worker/handler.ts"); - let bytes = module.source().await.unwrap(); - let text = std::str::from_utf8(&bytes).unwrap(); - assert!(!text.contains("import type { ConnInfo }")); - } - - #[tokio::test] - async fn eszipv1_iterator_yields_all_modules() { - let data = include_bytes!("./testdata/dotland.json"); - let eszip = EszipV1::parse(data).unwrap(); - assert_eq!(eszip.version, 1); - - let expected_modules: HashSet = [ - "file:///src/util/registry_utils.ts".to_string(), - "file:///src/worker/handler.ts".to_string(), - "file:///src/worker/main.ts".to_string(), - "file:///src/worker/registry.ts".to_string(), - "file:///src/worker/registry_config.ts".to_string(), - "file:///src/worker/suggestions.ts".to_string(), - "file:///src/worker/vscode.ts".to_string(), - "https://cdn.esm.sh/v64/twas@2.1.2/deno/twas.js".to_string(), - "https://deno.land/std@0.108.0/async/deadline.ts".to_string(), - "https://deno.land/std@0.108.0/async/debounce.ts".to_string(), - "https://deno.land/std@0.108.0/async/deferred.ts".to_string(), - "https://deno.land/std@0.108.0/async/delay.ts".to_string(), - "https://deno.land/std@0.108.0/async/mod.ts".to_string(), - "https://deno.land/std@0.108.0/async/mux_async_iterator.ts".to_string(), - "https://deno.land/std@0.108.0/async/pool.ts".to_string(), - "https://deno.land/std@0.108.0/async/tee.ts".to_string(), - "https://deno.land/std@0.108.0/http/server.ts".to_string(), - "https://deno.land/std@0.120.0/async/deadline.ts".to_string(), - "https://deno.land/std@0.120.0/async/debounce.ts".to_string(), - "https://deno.land/std@0.120.0/async/deferred.ts".to_string(), - "https://deno.land/std@0.120.0/async/delay.ts".to_string(), - "https://deno.land/std@0.120.0/async/mod.ts".to_string(), - "https://deno.land/std@0.120.0/async/mux_async_iterator.ts".to_string(), - "https://deno.land/std@0.120.0/async/pool.ts".to_string(), - "https://deno.land/std@0.120.0/async/tee.ts".to_string(), - "https://deno.land/std@0.120.0/fmt/colors.ts".to_string(), - "https://deno.land/std@0.120.0/http/http_status.ts".to_string(), - "https://deno.land/x/fuse@v6.4.1/dist/fuse.esm.js".to_string(), - "https://deno.land/x/g_a@0.1.2/mod.ts".to_string(), - "https://deno.land/x/oak_commons@0.1.1/negotiation.ts".to_string(), - "https://deno.land/x/oak_commons@0.1.1/negotiation/common.ts".to_string(), - "https://deno.land/x/oak_commons@0.1.1/negotiation/encoding.ts" - .to_string(), - "https://deno.land/x/oak_commons@0.1.1/negotiation/language.ts" - .to_string(), - "https://deno.land/x/oak_commons@0.1.1/negotiation/mediaType.ts" - .to_string(), - "https://deno.land/x/path_to_regexp@v6.2.0/index.ts".to_string(), - "https://deno.land/x/pretty_bytes@v1.0.5/mod.ts".to_string(), - "https://esm.sh/twas@2.1.2".to_string(), - ] - .into_iter() - .collect(); - let actual_modules = eszip - .into_iter() - .map(|(module_specifier, _)| module_specifier) - .collect(); - - assert_eq!(expected_modules, actual_modules); - } -} diff --git a/src/v2.rs b/src/v2.rs deleted file mode 100644 index 83f781a..0000000 --- a/src/v2.rs +++ /dev/null @@ -1,4016 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::borrow::Cow; -use std::collections::HashMap; -use std::collections::HashSet; -use std::collections::VecDeque; -use std::future::Future; -use std::hash::Hash; -use std::mem::size_of; -use std::sync::Arc; -use std::sync::Mutex; -use std::task::Poll; -use std::task::Waker; - -use deno_ast::EmitOptions; -use deno_ast::ModuleSpecifier; -use deno_ast::SourceMapOption; -use deno_ast::TranspileModuleOptions; -use deno_ast::TranspileOptions; -use deno_graph::ModuleGraph; -use deno_graph::ast::CapturingEsParser; -use deno_graph::ast::EsParser; -use deno_graph::ast::ParseOptions; -use deno_npm::NpmPackageId; -use deno_npm::resolution::SerializedNpmResolutionSnapshot; -use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage; -use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; -use deno_semver::StackString; -use deno_semver::npm::NpmPackageNvReference; -use deno_semver::package::PackageNv; -use deno_semver::package::PackageNvReference; -use deno_semver::package::PackageReq; -use futures::future::poll_fn; -use futures::io::AsyncReadExt; -use hashlink::linked_hash_map::LinkedHashMap; -use indexmap::IndexMap; -use indexmap::IndexSet; -pub use url::Url; - -use crate::Module; -use crate::ModuleInner; -pub use crate::ModuleKind; -use crate::error::ParseError; - -const ESZIP_V2_MAGIC: &[u8; 8] = b"ESZIP_V2"; -const ESZIP_V2_1_MAGIC: &[u8; 8] = b"ESZIP2.1"; -const ESZIP_V2_2_MAGIC: &[u8; 8] = b"ESZIP2.2"; -const ESZIP_V2_3_MAGIC: &[u8; 8] = b"ESZIP2.3"; -const LATEST_VERSION: EszipVersion = EszipVersion::V2_3; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] -pub(crate) enum EszipVersion { - // these numbers are just for ordering - V2 = 0, - V2_1 = 1, - V2_2 = 2, - V2_3 = 3, -} - -impl EszipVersion { - pub fn from_magic(magic: &[u8; 8]) -> Option { - match magic { - ESZIP_V2_MAGIC => Some(Self::V2), - ESZIP_V2_1_MAGIC => Some(Self::V2_1), - ESZIP_V2_2_MAGIC => Some(Self::V2_2), - ESZIP_V2_3_MAGIC => Some(Self::V2_3), - _ => None, - } - } - - pub fn to_magic(self) -> &'static [u8; 8] { - match self { - Self::V2 => ESZIP_V2_MAGIC, - Self::V2_1 => ESZIP_V2_1_MAGIC, - Self::V2_2 => ESZIP_V2_2_MAGIC, - Self::V2_3 => ESZIP_V2_3_MAGIC, - } - } -} - -#[derive(Debug, PartialEq)] -#[repr(u8)] -enum HeaderFrameKind { - Module = 0, - Redirect = 1, - NpmSpecifier = 2, -} - -#[derive(Debug, Default, Clone)] -pub struct EszipV2Modules(Arc>>); - -impl EszipV2Modules { - pub(crate) async fn get_module_source( - &self, - specifier: &str, - ) -> Option> { - poll_fn(|cx| { - let mut modules = self.0.lock().unwrap(); - let module = modules.get_mut(specifier).unwrap(); - let slot = match module { - EszipV2Module::Module { source, .. } => source, - EszipV2Module::Redirect { .. } => { - panic!("redirects are already resolved") - } - }; - match slot { - EszipV2SourceSlot::Pending { wakers, .. } => { - wakers.push(cx.waker().clone()); - Poll::Pending - } - EszipV2SourceSlot::Ready(bytes) => Poll::Ready(Some(bytes.clone())), - EszipV2SourceSlot::Taken => Poll::Ready(None), - } - }) - .await - } - - pub(crate) async fn take_module_source( - &self, - specifier: &str, - ) -> Option> { - poll_fn(|cx| { - let mut modules = self.0.lock().unwrap(); - let module = modules.get_mut(specifier).unwrap(); - let slot = match module { - EszipV2Module::Module { source, .. } => source, - EszipV2Module::Redirect { .. } => { - panic!("redirects are already resolved") - } - }; - match slot { - EszipV2SourceSlot::Pending { wakers, .. } => { - wakers.push(cx.waker().clone()); - return Poll::Pending; - } - EszipV2SourceSlot::Ready(_) => {} - EszipV2SourceSlot::Taken => return Poll::Ready(None), - }; - let EszipV2SourceSlot::Ready(bytes) = - std::mem::replace(slot, EszipV2SourceSlot::Taken) - else { - unreachable!() - }; - Poll::Ready(Some(bytes)) - }) - .await - } - - pub(crate) async fn get_module_source_map( - &self, - specifier: &str, - ) -> Option> { - poll_fn(|cx| { - let mut modules = self.0.lock().unwrap(); - let module = modules.get_mut(specifier).unwrap(); - let slot = match module { - EszipV2Module::Module { source_map, .. } => source_map, - EszipV2Module::Redirect { .. } => { - panic!("redirects are already resolved") - } - }; - match slot { - EszipV2SourceSlot::Pending { wakers, .. } => { - wakers.push(cx.waker().clone()); - Poll::Pending - } - EszipV2SourceSlot::Ready(bytes) => Poll::Ready(Some(bytes.clone())), - EszipV2SourceSlot::Taken => Poll::Ready(None), - } - }) - .await - } - - pub(crate) async fn take_module_source_map( - &self, - specifier: &str, - ) -> Option> { - let source = poll_fn(|cx| { - let mut modules = self.0.lock().unwrap(); - let module = modules.get_mut(specifier).unwrap(); - let slot = match module { - EszipV2Module::Module { source_map, .. } => source_map, - EszipV2Module::Redirect { .. } => { - panic!("redirects are already resolved") - } - }; - match slot { - EszipV2SourceSlot::Pending { wakers, .. } => { - wakers.push(cx.waker().clone()); - Poll::Pending - } - EszipV2SourceSlot::Ready(bytes) => Poll::Ready(Some(bytes.clone())), - EszipV2SourceSlot::Taken => Poll::Ready(None), - } - }) - .await; - - // Drop the source map from memory. - let mut modules = self.0.lock().unwrap(); - let module = modules.get_mut(specifier).unwrap(); - match module { - EszipV2Module::Module { source_map, .. } => { - *source_map = EszipV2SourceSlot::Taken; - } - EszipV2Module::Redirect { .. } => { - panic!("redirects are already resolved") - } - }; - source - } -} - -#[derive(Debug, Clone, Copy)] -struct Options { - /// Hash Function used to checksum the contents of the eszip when encoding/decoding - /// - /// If the eszip does not include the option, it defaults to `[Checksum::NoChecksum]` in >=v2.2 - /// and `[Checksum::Sha256]` in older versions. It is `None` when the eszip header includes a - /// checksum that this version of the library does not know. - checksum: Option, - - /// Size in Bytes of the hash function digest. - /// - /// Defaults to the known length of the configured hash function. Useful in order to ensure forwards compatibility, - /// otherwise the parser does not know how many bytes to read. - checksum_size: Option, -} - -impl Options { - fn default_for_version(version: EszipVersion) -> Self { - let defaults = Self { - checksum: Some(Checksum::NoChecksum), - checksum_size: Default::default(), - }; - #[cfg(feature = "sha256")] - let mut defaults = defaults; - if matches!(version, EszipVersion::V2 | EszipVersion::V2_1) { - // versions prior to v2.2 default to checksuming with SHA256 - #[cfg(feature = "sha256")] - { - defaults.checksum = Some(Checksum::Sha256); - } - } - defaults - } -} - -impl Default for Options { - fn default() -> Self { - Self::default_for_version(LATEST_VERSION) - } -} - -impl Options { - /// Get the size in Bytes of the source hashes - /// - /// If the eszip has an explicit digest size, returns that. Otherwise, returns - /// the default digest size of the [`Self::checksum`]. If the eszip - /// does not have either, returns `None`. - fn checksum_size(self) -> Option { - self - .checksum_size - .or_else(|| Some(self.checksum?.digest_size())) - } -} - -/// A URL that can be designated as the base for relative URLs -/// in an eszip. -/// -/// After creation, this URL may be used to get the key for a -/// module in the eszip. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct EszipRelativeFileBaseUrl<'a>(&'a Url); - -impl<'a> From<&'a Url> for EszipRelativeFileBaseUrl<'a> { - fn from(url: &'a Url) -> Self { - Self(url) - } -} - -impl<'a> EszipRelativeFileBaseUrl<'a> { - pub fn new(url: &'a Url) -> Self { - debug_assert_eq!(url.scheme(), "file"); - Self(url) - } - - /// Gets the eszip module map key of the provided specifier. - /// - /// * Descendant file specifiers will be made relative to the base. - /// * Non-descendant file specifiers will stay as-is (absolute). - /// * Non-file specifiers will stay as-is. - pub fn specifier_key<'b>(&self, target: &'b Url) -> Cow<'b, str> { - if target.scheme() != "file" { - return Cow::Borrowed(target.as_str()); - } - - match self.0.make_relative(target) { - Some(relative) => { - if relative.starts_with("../") { - Cow::Borrowed(target.as_str()) - } else { - Cow::Owned(relative) - } - } - None => Cow::Borrowed(target.as_str()), - } - } - - pub fn inner(&self) -> &Url { - self.0 - } -} - -/// Resolves whether the module is ESM or CommonJS for transpilation. -pub trait ModuleKindResolver { - fn module_kind( - &self, - module: &deno_graph::JsModule, - ) -> Option; -} - -impl<'a> Default for &'a dyn ModuleKindResolver { - fn default() -> &'a dyn ModuleKindResolver { - &NullModuleKindResolver - } -} - -pub struct NullModuleKindResolver; - -impl ModuleKindResolver for NullModuleKindResolver { - fn module_kind( - &self, - _module: &deno_graph::JsModule, - ) -> Option { - None - } -} - -pub struct FromGraphOptions<'a> { - pub graph: ModuleGraph, - pub parser: CapturingEsParser<'a>, - pub module_kind_resolver: &'a dyn ModuleKindResolver, - pub transpile_options: TranspileOptions, - pub emit_options: EmitOptions, - /// Base to make all descendant file:/// modules relative to. - /// - /// Note: When a path is above the base it will be left absolute. - pub relative_file_base: Option>, - pub npm_packages: Option, - pub npm_snapshot: ValidSerializedNpmResolutionSnapshot, -} - -/// Provide the source code of the Npm packages to include in the eszip -/// -/// When building the eszip from a [`ModuleGraph`], use this struct to -/// provide all the Npm packages that should be included in it. All the -/// modules of all the packages in this struct are guaranteed to be included in the eszip. -/// The npm modules that are imported from esm modules (using `npm:` specifiers) are included in -/// the eszip following the graph order (BFS), for an optimal loading of these modules -/// by Deno. The rest of the modules that might remain are appended at the end of the eszip. -/// -/// Npm Packages are formed by modules, and optionally "meta" files. The most basic "meta" file -/// that any Npm package usually have is a package.json, but there can additionally be other -/// meta files like manifests and the like to assist in the loading of the package. Both -/// modules and meta-modules have an arbitrary name identifying them within the eszip. -#[derive(Debug, Default, Clone)] -pub struct FromGraphNpmPackages { - packages: IndexMap, - // Track any package that has had any module or meta-module taken - partially_taken: IndexSet, -} - -impl FromGraphNpmPackages { - fn get_mut( - &mut self, - package_nv: &PackageNv, - ) -> Option<&mut FromGraphNpmPackage> { - self.packages.get_mut(package_nv) - } - - pub fn new() -> Self { - Default::default() - } - - pub fn add_package_with_maybe_meta( - &mut self, - package_id: PackageNv, - package_jsons: Option>, - meta_modules: Option>, - modules: IndexMap, - ) { - self.packages.insert( - package_id, - FromGraphNpmPackage { - package_jsons, - meta_modules: meta_modules - .or(FromGraphNpmPackage::default().meta_modules), - modules, - }, - ); - } - - pub fn add_package( - &mut self, - package_id: PackageNv, - package_jsons: impl IntoIterator, - modules: impl IntoIterator, - ) where - S: Into>, - N: Into, - { - self.add_package_with_maybe_meta( - package_id, - Some( - package_jsons - .into_iter() - .map(|package_json| FromGraphNpmModule { - specifier: package_json.0.into(), - source: package_json.1.into(), - }) - .collect(), - ), - None, - modules - .into_iter() - .map(|(reference, (specifier, source))| { - ( - reference, - FromGraphNpmModule { - specifier: specifier.into(), - source: source.into(), - }, - ) - }) - .collect(), - ); - } - - pub fn add_package_with_meta( - &mut self, - package_id: PackageNv, - package_jsons: impl IntoIterator, - meta_modules: impl IntoIterator, - modules: impl IntoIterator, - ) where - N: Into, - S: Into>, - { - self.add_package_with_maybe_meta( - package_id, - Some( - package_jsons - .into_iter() - .map(|package_json| FromGraphNpmModule { - specifier: package_json.0.into(), - source: package_json.1.into(), - }) - .collect(), - ), - Some( - meta_modules - .into_iter() - .map(|(specifier, source)| FromGraphNpmModule { - specifier: specifier.into(), - source: source.into(), - }) - .collect(), - ), - modules - .into_iter() - .map(|(reference, (specifier, source))| { - ( - reference, - FromGraphNpmModule { - specifier: specifier.into(), - source: source.into(), - }, - ) - }) - .collect(), - ); - } - - pub fn add_module( - &mut self, - package_nv_ref: NpmPackageNvReference, - specifier: impl Into, - source: impl Into>, - ) { - self - .packages - .entry(package_nv_ref.nv().clone()) - .or_default() - .modules - .insert( - package_nv_ref, - FromGraphNpmModule { - specifier: specifier.into(), - source: source.into(), - }, - ); - } - - pub fn add_meta( - &mut self, - package_nv_ref: &NpmPackageNvReference, - specifier: impl Into, - source: impl Into>, - ) { - self - .packages - .entry(package_nv_ref.nv().clone()) - .or_default() - .meta_modules - .get_or_insert_with(Vec::new) - .push(FromGraphNpmModule { - specifier: specifier.into(), - source: source.into(), - }); - } - - pub fn add_package_json( - &mut self, - package_nv_ref: &NpmPackageNvReference, - specifier: impl Into, - source: impl Into>, - ) { - self - .packages - .entry(package_nv_ref.nv().clone()) - .or_default() - .package_jsons - .get_or_insert_with(Vec::new) - .push(FromGraphNpmModule { - specifier: specifier.into(), - source: source.into(), - }); - } - - fn take_package(&mut self, nv: &PackageNv) -> Option { - self.partially_taken.shift_remove(nv); - self.packages.shift_remove(nv) - } - - fn take_meta_modules( - &mut self, - nv: PackageNv, - ) -> Option> { - let meta_module = self.get_mut(&nv)?.meta_modules.take(); - self.partially_taken.insert(nv); - meta_module - } - - fn take_package_jsons( - &mut self, - nv: PackageNv, - ) -> Option> { - let package_json = self.get_mut(&nv)?.package_jsons.take(); - self.partially_taken.insert(nv); - package_json - } - - fn take_module( - &mut self, - nv_reference: NpmPackageNvReference, - ) -> Option { - let module = self - .get_mut(nv_reference.nv())? - .modules - .shift_remove(&nv_reference); - self.partially_taken.insert(nv_reference.into_inner().nv); - module - } - - fn drain(&mut self) -> impl Iterator + '_ { - // first drain those packages that have had at least one module taken - let remaining_packages: IndexSet<_> = - std::mem::take(&mut self.partially_taken) - .into_iter() - .chain(self.packages.keys().cloned()) - .collect(); - - remaining_packages - .into_iter() - .filter_map(|nv| self.packages.shift_remove(&nv)) - .flat_map(|package| { - package - .meta_modules - .into_iter() - .chain(package.package_jsons) - .flatten() - .chain(package.modules.into_values()) - }) - } -} - -#[derive(Debug, Clone, Default)] -struct FromGraphNpmPackage { - package_jsons: Option>, - meta_modules: Option>, - modules: IndexMap, -} - -#[derive(Debug, Clone)] -pub struct FromGraphNpmModule { - specifier: String, - source: Vec, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum Checksum { - NoChecksum = 0, - #[cfg(feature = "sha256")] - Sha256 = 1, - #[cfg(feature = "xxhash3")] - XxHash3 = 2, -} - -impl Checksum { - const fn digest_size(self) -> u8 { - match self { - Self::NoChecksum => 0, - #[cfg(feature = "sha256")] - Self::Sha256 => 32, - #[cfg(feature = "xxhash3")] - Self::XxHash3 => 8, - } - } - - fn from_u8(discriminant: u8) -> Option { - Some(match discriminant { - 0 => Self::NoChecksum, - #[cfg(feature = "sha256")] - 1 => Self::Sha256, - #[cfg(feature = "xxhash3")] - 2 => Self::XxHash3, - _ => return None, - }) - } - fn hash( - self, - #[cfg_attr( - not(any(feature = "sha256", feature = "xxhash3")), - allow(unused) - )] - bytes: &[u8], - ) -> Vec { - match self { - Self::NoChecksum => Vec::new(), - #[cfg(feature = "sha256")] - Self::Sha256 => ::digest(bytes) - .as_slice() - .to_vec(), - #[cfg(feature = "xxhash3")] - Self::XxHash3 => xxhash_rust::xxh3::xxh3_64(bytes).to_be_bytes().into(), - } - } -} - -/// Version 2 of the Eszip format. This format supports streaming sources and -/// source maps. -#[derive(Debug, Default)] -pub struct EszipV2 { - modules: EszipV2Modules, - npm_snapshot: Option, - options: Options, -} - -#[derive(Debug)] -pub enum EszipV2Module { - Module { - kind: ModuleKind, - source: EszipV2SourceSlot, - source_map: EszipV2SourceSlot, - }, - Redirect { - target: String, - }, -} - -#[derive(Debug)] -pub enum EszipV2SourceSlot { - Pending { - offset: usize, - length: usize, - wakers: Vec, - }, - Ready(Arc<[u8]>), - Taken, -} - -impl EszipV2SourceSlot { - fn bytes(&self) -> &[u8] { - match self { - EszipV2SourceSlot::Ready(v) => v, - _ => panic!("EszipV2SourceSlot::bytes() called on a pending slot"), - } - } -} - -impl EszipV2 { - pub fn has_magic(buffer: &[u8]) -> bool { - if buffer.len() < 8 { - false - } else { - EszipVersion::from_magic(&buffer[0..8].try_into().unwrap()).is_some() - } - } - - /// Parse a EszipV2 from an AsyncRead stream. This function returns once the - /// header section of the eszip has been parsed. Once this function returns, - /// the data section will not necessarially have been parsed yet. To parse - /// the data section, poll/await the future returned in the second tuple slot. - pub async fn parse( - mut reader: futures::io::BufReader, - ) -> Result< - ( - EszipV2, - impl Future, ParseError>>, - ), - ParseError, - > { - let mut magic = [0u8; 8]; - reader.read_exact(&mut magic).await?; - - let Some(version) = EszipVersion::from_magic(&magic) else { - return Err(ParseError::InvalidV2); - }; - - Self::parse_with_version(version, reader).await - } - - pub(super) async fn parse_with_version( - version: EszipVersion, - mut reader: futures::io::BufReader, - ) -> Result< - ( - EszipV2, - impl Future, ParseError>>, - ), - ParseError, - > { - let supports_npm = version != EszipVersion::V2; - let supports_options = version >= EszipVersion::V2_2; - - let mut options = Options::default_for_version(version); - - if supports_options { - let mut pre_options = options; - // First read options without checksum, then reread and validate if necessary - pre_options.checksum = Some(Checksum::NoChecksum); - pre_options.checksum_size = None; - let options_header = Section::read(&mut reader, pre_options).await?; - if options_header.content_len() % 2 != 0 { - return Err(ParseError::InvalidV22OptionsHeader(String::from( - "options are expected to be byte tuples", - ))); - } - - for option in options_header.content().chunks(2) { - let (option, value) = (option[0], option[1]); - match option { - 0 => { - options.checksum = Checksum::from_u8(value); - } - 1 => { - options.checksum_size = Some(value); - } - _ => {} // Ignore unknown options for forward compatibility - } - } - if options.checksum_size().is_none() { - return Err(ParseError::InvalidV22OptionsHeader(String::from( - "checksum size must be known", - ))); - } - - if let Some(1..) = options.checksum_size() { - // If the eszip has some checksum configured, the options header is also checksumed. Reread - // it again with the checksum and validate it - let options_header_with_checksum = Section::read_with_size( - options_header.content().chain(&mut reader), - options, - options_header.content_len(), - ) - .await?; - if !options_header_with_checksum.is_checksum_valid() { - return Err(ParseError::InvalidV22OptionsHeaderHash); - } - } - } - - let modules_header = Section::read(&mut reader, options).await?; - if !modules_header.is_checksum_valid() { - return Err(ParseError::InvalidV2HeaderHash); - } - - let mut modules = LinkedHashMap::::new(); - let mut npm_specifiers = HashMap::new(); - - let mut read = 0; - - // This macro reads n number of bytes from the header section. If the header - // section is not long enough, this function will be early exited with an - // error. - macro_rules! read { - ($n:expr, $err:expr) => {{ - if read + $n > modules_header.content_len() { - return Err(ParseError::InvalidV2Header($err)); - } - let start = read; - read += $n; - &modules_header.content()[start..read] - }}; - } - - while read < modules_header.content_len() { - let specifier_len = - u32::from_be_bytes(read!(4, "specifier len").try_into().unwrap()) - as usize; - let specifier = - String::from_utf8(read!(specifier_len, "specifier").to_vec()) - .map_err(|_| ParseError::InvalidV2Specifier(read))?; - - let entry_kind = read!(1, "entry kind")[0]; - match entry_kind { - 0 => { - let source_offset = - u32::from_be_bytes(read!(4, "source offset").try_into().unwrap()); - let source_len = - u32::from_be_bytes(read!(4, "source len").try_into().unwrap()); - let source_map_offset = u32::from_be_bytes( - read!(4, "source map offset").try_into().unwrap(), - ); - let source_map_len = - u32::from_be_bytes(read!(4, "source map len").try_into().unwrap()); - let kind = match read!(1, "module kind")[0] { - 0 => ModuleKind::JavaScript, - 1 => ModuleKind::Json, - 2 => ModuleKind::Jsonc, - 3 => ModuleKind::OpaqueData, - 4 => ModuleKind::Wasm, - n => return Err(ParseError::InvalidV2ModuleKind(n, read)), - }; - let source = if source_offset == 0 && source_len == 0 { - EszipV2SourceSlot::Ready(Arc::new([])) - } else { - EszipV2SourceSlot::Pending { - offset: source_offset as usize, - length: source_len as usize, - wakers: vec![], - } - }; - let source_map = if source_map_offset == 0 && source_map_len == 0 { - EszipV2SourceSlot::Ready(Arc::new([])) - } else { - EszipV2SourceSlot::Pending { - offset: source_map_offset as usize, - length: source_map_len as usize, - wakers: vec![], - } - }; - let module = EszipV2Module::Module { - kind, - source, - source_map, - }; - modules.insert(specifier, module); - } - 1 => { - let target_len = - u32::from_be_bytes(read!(4, "target len").try_into().unwrap()) - as usize; - let target = String::from_utf8(read!(target_len, "target").to_vec()) - .map_err(|_| ParseError::InvalidV2Specifier(read))?; - modules.insert(specifier, EszipV2Module::Redirect { target }); - } - 2 if supports_npm => { - // npm specifier - let pkg_id = - u32::from_be_bytes(read!(4, "npm package id").try_into().unwrap()); - npm_specifiers.insert(specifier, EszipNpmPackageIndex(pkg_id)); - } - n => return Err(ParseError::InvalidV2EntryKind(n, read)), - }; - } - - let npm_snapshot = if supports_npm { - read_npm_section(&mut reader, options, npm_specifiers).await? - } else { - None - }; - - let mut source_offsets = modules - .iter() - .filter_map(|(specifier, m)| { - if let EszipV2Module::Module { - source: EszipV2SourceSlot::Pending { offset, length, .. }, - .. - } = m - { - Some((*offset, (*length, specifier.clone()))) - } else { - None - } - }) - .collect::>(); - - let mut source_map_offsets = modules - .iter() - .filter_map(|(specifier, m)| { - if let EszipV2Module::Module { - source_map: EszipV2SourceSlot::Pending { offset, length, .. }, - .. - } = m - { - Some((*offset, (*length, specifier.clone()))) - } else { - None - } - }) - .collect::>(); - - let modules = Arc::new(Mutex::new(modules)); - let modules_ = modules.clone(); - - let fut = async move { - let modules = modules_; - - let sources_len = read_u32(&mut reader).await? as usize; - let mut read = 0; - - while read < sources_len { - let (length, specifier) = source_offsets - .remove(&read) - .ok_or(ParseError::InvalidV2SourceOffset(read))?; - - let source_bytes = - Section::read_with_size(&mut reader, options, length).await?; - - if !source_bytes.is_checksum_valid() { - return Err(ParseError::InvalidV2SourceHash(specifier)); - } - read += source_bytes.total_len(); - - let wakers = { - let mut modules = modules.lock().unwrap(); - let module = modules.get_mut(&specifier).expect("module not found"); - match module { - EszipV2Module::Module { source, .. } => { - let slot = std::mem::replace( - source, - EszipV2SourceSlot::Ready(Arc::from( - source_bytes.into_content(), - )), - ); - - match slot { - EszipV2SourceSlot::Pending { wakers, .. } => wakers, - _ => panic!("already populated source slot"), - } - } - _ => panic!("invalid module type"), - } - }; - for w in wakers { - w.wake(); - } - } - - let source_maps_len = read_u32(&mut reader).await? as usize; - let mut read = 0; - - while read < source_maps_len { - let (length, specifier) = source_map_offsets - .remove(&read) - .ok_or(ParseError::InvalidV2SourceOffset(read))?; - - let source_map_bytes = - Section::read_with_size(&mut reader, options, length).await?; - if !source_map_bytes.is_checksum_valid() { - return Err(ParseError::InvalidV2SourceHash(specifier)); - } - read += source_map_bytes.total_len(); - - let wakers = { - let mut modules = modules.lock().unwrap(); - let module = modules.get_mut(&specifier).expect("module not found"); - match module { - EszipV2Module::Module { source_map, .. } => { - let slot = std::mem::replace( - source_map, - EszipV2SourceSlot::Ready(Arc::from( - source_map_bytes.into_content(), - )), - ); - - match slot { - EszipV2SourceSlot::Pending { wakers, .. } => wakers, - _ => panic!("already populated source_map slot"), - } - } - _ => panic!("invalid module type"), - } - }; - for w in wakers { - w.wake(); - } - } - - Ok(reader) - }; - - Ok(( - EszipV2 { - modules: EszipV2Modules(modules), - npm_snapshot, - options, - }, - fut, - )) - } - - /// Add an import map to the eszip archive. The import map will always be - /// placed at the top of the archive, so it can be read before any other - /// modules are loaded. - /// - /// If a module with this specifier is already present, its source is replaced - /// with the new source. - pub fn add_import_map( - &mut self, - kind: ModuleKind, - specifier: String, - source: Arc<[u8]>, - ) { - debug_assert!(matches!(kind, ModuleKind::Json | ModuleKind::Jsonc)); - self.add_to_front(kind, specifier.clone(), source, []); - } - - /// Add an opaque data to the eszip. - pub fn add_opaque_data(&mut self, specifier: String, data: Arc<[u8]>) { - let mut modules = self.modules.0.lock().unwrap(); - modules.insert( - specifier, - EszipV2Module::Module { - kind: ModuleKind::OpaqueData, - source: EszipV2SourceSlot::Ready(data), - source_map: EszipV2SourceSlot::Ready(Arc::new([])), - }, - ); - } - - // Add a module to the front of the eszip - pub fn add_to_front( - &mut self, - kind: ModuleKind, - specifier: String, - data: impl Into>, - source_map: impl Into>, - ) { - let mut modules = self.modules.0.lock().unwrap(); - modules.insert( - specifier.clone(), - EszipV2Module::Module { - kind, - source: EszipV2SourceSlot::Ready(data.into()), - source_map: EszipV2SourceSlot::Ready(source_map.into()), - }, - ); - modules.to_front(&specifier); - } - - /// Takes an npm resolution snapshot from the eszip. - pub fn take_npm_snapshot( - &mut self, - ) -> Option { - self.npm_snapshot.take() - } - - /// Configure the hash function with which to checksum the source of the modules - /// - /// Defaults to `[Checksum::NoChecksum]`. - pub fn set_checksum(&mut self, checksum: Checksum) { - self.options.checksum = Some(checksum); - } - - /// Check if the eszip contents have been (or can be) checksumed - /// - /// Returns false if the parsed eszip is not configured with checksum or if it is configured with - /// a checksum function that the current version of the library does not know (see - /// [`Self::should_be_checksumed()`]). In that case, the parsing has continued without checksuming - /// the module's source, therefore proceed with caution. - pub fn is_checksumed(&self) -> bool { - self.should_be_checksumed() && self.options.checksum.is_some() - } - - /// Check if the eszip contents are expected to be checksumed - /// - /// Returns false if the eszip is not configured with checksum. if a parsed eszip is configured - /// with a checksum function that the current version of the library does not know, this method - /// returns true, and [`Self::is_checksumed()`] returns false. In that case, the parsing has - /// continued without checksuming the module's source, therefore proceed with caution. - pub fn should_be_checksumed(&self) -> bool { - self.options.checksum != Some(Checksum::NoChecksum) - } - - /// Serialize the eszip archive into a byte buffer. - pub fn into_bytes(self) -> Vec { - fn append_string(bytes: &mut Vec, string: &str) { - let len = string.len() as u32; - bytes.extend_from_slice(&len.to_be_bytes()); - bytes.extend_from_slice(string.as_bytes()); - } - - let (checksum, checksum_size) = self - .options - .checksum - .zip(self.options.checksum_size()) - .expect("checksum function should be known"); - - debug_assert_eq!( - checksum_size, - checksum.digest_size(), - "customizing the checksum size should not be posible" - ); - - let mut options_header = LATEST_VERSION.to_magic().to_vec(); - - let options_header_length_pos = options_header.len(); - const OPTIONS_HEADER_LENGTH_SIZE: usize = size_of::(); - options_header.extend_from_slice(&[0; OPTIONS_HEADER_LENGTH_SIZE]); // Reserve for length - - let options_header_start = options_header.len(); - options_header.extend_from_slice(&[0, checksum as u8]); - options_header.extend_from_slice(&[1, checksum_size]); - - let options_header_length = - (options_header.len() - options_header_start) as u32; - options_header[options_header_length_pos..options_header_start] - .copy_from_slice(&options_header_length.to_be_bytes()); - let options_header_hash = - checksum.hash(&options_header[options_header_start..]); - options_header.extend_from_slice(&options_header_hash); - - let mut modules_header = options_header; - let modules_header_length_pos = modules_header.len(); - modules_header.extend_from_slice(&[0u8; 4]); // add 4 bytes of space to put the header length in later - let modules_header_start = modules_header.len(); - let mut npm_bytes: Vec = Vec::new(); - let mut sources: Vec = Vec::new(); - let mut source_maps: Vec = Vec::new(); - - let modules = self.modules.0.lock().unwrap(); - - for (specifier, module) in modules.iter() { - append_string(&mut modules_header, specifier); - - match module { - EszipV2Module::Module { - kind, - source, - source_map, - } => { - modules_header.push(HeaderFrameKind::Module as u8); - - // add the source to the `sources` bytes - let source_bytes = source.bytes(); - let source_length = source_bytes.len() as u32; - if source_length > 0 { - let source_offset = sources.len() as u32; - sources.extend_from_slice(source_bytes); - sources.extend_from_slice(&checksum.hash(source_bytes)); - - modules_header.extend_from_slice(&source_offset.to_be_bytes()); - modules_header.extend_from_slice(&source_length.to_be_bytes()); - } else { - modules_header.extend_from_slice(&0u32.to_be_bytes()); - modules_header.extend_from_slice(&0u32.to_be_bytes()); - } - - // add the source map to the `source_maps` bytes - let source_map_bytes = source_map.bytes(); - let source_map_length = source_map_bytes.len() as u32; - if source_map_length > 0 { - let source_map_offset = source_maps.len() as u32; - source_maps.extend_from_slice(source_map_bytes); - source_maps.extend_from_slice(&checksum.hash(source_map_bytes)); - - modules_header.extend_from_slice(&source_map_offset.to_be_bytes()); - modules_header.extend_from_slice(&source_map_length.to_be_bytes()); - } else { - modules_header.extend_from_slice(&0u32.to_be_bytes()); - modules_header.extend_from_slice(&0u32.to_be_bytes()); - } - - // add module kind to the header - modules_header.push(*kind as u8); - } - EszipV2Module::Redirect { target } => { - modules_header.push(HeaderFrameKind::Redirect as u8); - let target_bytes = target.as_bytes(); - let target_length = target_bytes.len() as u32; - modules_header.extend_from_slice(&target_length.to_be_bytes()); - modules_header.extend_from_slice(target_bytes); - } - } - } - - // add npm snapshot entries to the header and fill the npm bytes - if let Some(npm_snapshot) = self.npm_snapshot { - let mut npm_snapshot = npm_snapshot.into_serialized(); - npm_snapshot.packages.sort_by(|a, b| a.id.cmp(&b.id)); // determinism - let ids_to_eszip_ids = npm_snapshot - .packages - .iter() - .enumerate() - .map(|(i, pkg)| (&pkg.id, i as u32)) - .collect::>(); - - let mut root_packages: Vec<_> = - npm_snapshot.root_packages.iter().collect(); - root_packages.sort(); - for (req, id) in root_packages { - append_string(&mut modules_header, &req.to_string()); - modules_header.push(HeaderFrameKind::NpmSpecifier as u8); - let id = ids_to_eszip_ids.get(&id).unwrap(); - modules_header.extend_from_slice(&id.to_be_bytes()); - } - - for pkg in &npm_snapshot.packages { - append_string(&mut npm_bytes, &pkg.id.as_serialized()); - let deps_len = pkg.dependencies.len() as u32; - npm_bytes.extend_from_slice(&deps_len.to_be_bytes()); - let mut deps: Vec<_> = pkg.dependencies.iter().collect(); - deps.sort(); - for (req, id) in deps { - append_string(&mut npm_bytes, &req.to_string()); - let id = ids_to_eszip_ids.get(&id).unwrap(); - npm_bytes.extend_from_slice(&id.to_be_bytes()); - } - } - } - - // populate header length - let modules_header_length = - (modules_header.len() - modules_header_start) as u32; - modules_header[modules_header_length_pos..modules_header_start] - .copy_from_slice(&modules_header_length.to_be_bytes()); - - // add header hash - let modules_header_bytes = &modules_header[modules_header_start..]; - modules_header.extend_from_slice(&checksum.hash(modules_header_bytes)); - - let mut bytes = modules_header; - - let npm_bytes_len = npm_bytes.len() as u32; - bytes.extend_from_slice(&npm_bytes_len.to_be_bytes()); - bytes.extend_from_slice(&npm_bytes); - bytes.extend_from_slice(&checksum.hash(&npm_bytes)); - - // add sources - let sources_len = sources.len() as u32; - bytes.extend_from_slice(&sources_len.to_be_bytes()); - bytes.extend_from_slice(&sources); - - let source_maps_len = source_maps.len() as u32; - bytes.extend_from_slice(&source_maps_len.to_be_bytes()); - bytes.extend_from_slice(&source_maps); - - bytes - } - - /// Turn a [deno_graph::ModuleGraph] into an [EszipV2]. All modules from the - /// graph will be transpiled and stored in the eszip archive. - /// - /// The ordering of the modules in the graph is dependant on the module graph - /// tree. The root module is added to the top of the archive, and the leaves - /// to the end. This allows for efficient deserialization of the archive right - /// into an isolate. - pub fn from_graph(opts: FromGraphOptions) -> Result { - let mut emit_options = opts.emit_options; - emit_options.inline_sources = true; - if emit_options.source_map == SourceMapOption::Inline { - emit_options.source_map = SourceMapOption::Separate; - } - - let mut modules = LinkedHashMap::new(); - - fn resolve_specifier_key<'a>( - specifier: &'a Url, - relative_file_base: Option, - ) -> Result, anyhow::Error> { - if let Some(relative_file_base) = relative_file_base { - Ok(relative_file_base.specifier_key(specifier)) - } else { - Ok(Cow::Borrowed(specifier.as_str())) - } - } - - #[derive(Debug, Clone, Copy)] - enum ToVisit<'a> { - PackageMeta { - module_specifier: &'a ModuleSpecifier, - }, - Package { - module_specifier: &'a ModuleSpecifier, - }, - Module { - specifier: &'a ModuleSpecifier, - is_dynamic: bool, - }, - } - - impl<'a> ToVisit<'a> { - fn is_dynamic(self) -> bool { - matches!( - self, - Self::Module { - is_dynamic: true, - .. - } - ) - } - - fn specifier(self) -> &'a ModuleSpecifier { - let (Self::Module { - specifier: module_specifier, - .. - } - | Self::PackageMeta { module_specifier } - | Self::Package { module_specifier }) = self; - module_specifier - } - - fn should_visit_package_meta(self) -> bool { - matches!(self, Self::PackageMeta { .. }) - } - - fn should_visit_whole_package(self) -> bool { - matches!(self, Self::Package { .. }) - } - } - - #[allow(clippy::too_many_arguments)] - fn visit_module<'a>( - graph: &'a ModuleGraph, - module_kind_provider: &dyn ModuleKindResolver, - parser: CapturingEsParser, - transpile_options: &TranspileOptions, - emit_options: &EmitOptions, - modules: &mut LinkedHashMap, - visited: ToVisit, - relative_file_base: Option, - npm_packages: Option<&mut FromGraphNpmPackages>, - npm_snapshot: &ValidSerializedNpmResolutionSnapshot, - ) -> Result< - Option> + 'a>>, - anyhow::Error, - > { - let module = match graph.try_get(visited.specifier()) { - Ok(Some(module)) => module, - Ok(None) => { - return Err(anyhow::anyhow!( - "module not found {}", - visited.specifier() - )); - } - Err(err) => { - if visited.is_dynamic() { - // dynamic imports are allowed to fail - return Ok(None); - } - return Err(anyhow::anyhow!( - "failed to load '{}': {}", - visited.specifier(), - err - )); - } - }; - - let specifier_key = - resolve_specifier_key(module.specifier(), relative_file_base)?; - if modules.contains_key(specifier_key.as_ref()) { - return Ok(None); - } - - match module { - deno_graph::Module::Js(module) => { - let source: Arc<[u8]>; - let source_map: Arc<[u8]>; - match module.media_type { - deno_graph::MediaType::JavaScript | deno_graph::MediaType::Mjs => { - source = Arc::from(module.source.text.clone()); - source_map = Arc::new([]); - } - deno_graph::MediaType::Jsx - | deno_graph::MediaType::TypeScript - | deno_graph::MediaType::Mts - | deno_graph::MediaType::Tsx - | deno_graph::MediaType::Dts - | deno_graph::MediaType::Dmts => { - let parsed_source = parser.parse_program(ParseOptions { - specifier: &module.specifier, - source: module.source.text.clone(), - media_type: module.media_type, - scope_analysis: false, - })?; - let emit_options = match relative_file_base { - Some(relative_file_base) - if emit_options.source_map_base.is_none() => - { - Cow::Owned(EmitOptions { - source_map_base: Some(relative_file_base.inner().clone()), - ..emit_options.clone() - }) - } - _ => Cow::Borrowed(emit_options), - }; - let emit = parsed_source - .transpile( - transpile_options, - &TranspileModuleOptions { - module_kind: module_kind_provider.module_kind(module), - }, - &emit_options, - )? - .into_source(); - source = emit.text.into_bytes().into(); - source_map = Arc::from( - emit.source_map.map(|s| s.into_bytes()).unwrap_or_default(), - ); - } - _ => { - return Err(anyhow::anyhow!( - "unsupported media type {} for {}", - module.media_type, - visited.specifier() - )); - } - }; - - let eszip_module = EszipV2Module::Module { - kind: ModuleKind::JavaScript, - source: EszipV2SourceSlot::Ready(source), - source_map: EszipV2SourceSlot::Ready(source_map), - }; - modules.insert(specifier_key.into_owned(), eszip_module); - - Ok(Some(Box::new(module.dependencies.values().filter_map( - |dependency| { - Some(ToVisit::Module { - specifier: dependency.get_code()?, - is_dynamic: dependency.is_dynamic, - }) - }, - )))) - } - deno_graph::Module::Wasm(module) => { - let eszip_module = EszipV2Module::Module { - kind: ModuleKind::Wasm, - source: EszipV2SourceSlot::Ready(module.source.clone()), - source_map: EszipV2SourceSlot::Ready(Arc::new([])), // doesn't seem ideal - }; - modules.insert(specifier_key.into_owned(), eszip_module); - - Ok(Some(Box::new(module.dependencies.values().filter_map( - |dependency| { - Some(ToVisit::Module { - specifier: dependency.get_code()?, - is_dynamic: dependency.is_dynamic, - }) - }, - )))) - } - deno_graph::Module::Json(module) => { - let eszip_module = EszipV2Module::Module { - kind: ModuleKind::Json, - source: EszipV2SourceSlot::Ready(module.source.text.clone().into()), - source_map: EszipV2SourceSlot::Ready(Arc::new([])), - }; - modules.insert(specifier_key.into_owned(), eszip_module); - Ok(None) - } - deno_graph::Module::Npm(module) => { - let Some(npm_packages) = npm_packages else { - return Ok(None); - }; - - let req_ref = &module.pkg_req_ref; - let serialize_npm_snapshot = npm_snapshot.as_serialized(); - let pkg_id = serialize_npm_snapshot.root_packages.get(req_ref.req()) - .ok_or_else(|| anyhow::anyhow!("Could not resolve package req '{}' from graph because it was missing in the provided npm snapshot.", req_ref.req()))?; - let pkg_nv = &pkg_id.nv; - let pkg_nv_reference = - NpmPackageNvReference::new(PackageNvReference { - nv: pkg_nv.clone(), - sub_path: req_ref.sub_path().map(|s| s.into()), - }); - - if visited.should_visit_package_meta() { - let meta_modules = npm_packages.take_meta_modules(pkg_nv.clone()); - let package_jsons = npm_packages.take_package_jsons(pkg_nv.clone()); - - for meta_module in - meta_modules.into_iter().chain(package_jsons).flatten() - { - modules.insert( - meta_module.specifier, - EszipV2Module::Module { - kind: ModuleKind::OpaqueData, - source: EszipV2SourceSlot::Ready(meta_module.source.into()), - source_map: EszipV2SourceSlot::Ready(Arc::new([])), - }, - ); - } - } else if visited.should_visit_whole_package() { - let package = npm_packages.take_package(pkg_nv); - if let Some(mut package) = package { - let modules_to_insert = package - .meta_modules - .into_iter() - .chain(package.package_jsons) - .flatten() - .chain(package.modules.shift_remove(&pkg_nv_reference)) - .chain(package.modules.into_values()); - for module in modules_to_insert { - modules.insert( - module.specifier, - EszipV2Module::Module { - kind: ModuleKind::OpaqueData, - source: EszipV2SourceSlot::Ready(module.source.into()), - source_map: EszipV2SourceSlot::Ready(Arc::new([])), - }, - ); - } - } - } else { - let module = npm_packages.take_module(pkg_nv_reference); - if let Some(module) = module { - modules.insert( - module.specifier, - EszipV2Module::Module { - kind: ModuleKind::OpaqueData, - source: EszipV2SourceSlot::Ready(module.source.into()), - source_map: EszipV2SourceSlot::Ready(Arc::new([])), - }, - ); - } - } - Ok(None) - } - deno_graph::Module::External(_) | deno_graph::Module::Node(_) => { - Ok(None) - } - } - } - - let mut npm_packages = opts.npm_packages; - let mut to_visit = - Vec::from_iter(opts.graph.roots.iter().rev().map(|specifier| { - ToVisit::Module { - specifier, - is_dynamic: false, - } - })); - let mut to_visit_npm_meta = VecDeque::new(); - let mut to_visit_npm = VecDeque::new(); - let mut to_visit_dynamic = VecDeque::new(); - // deno_core's module loading traverses the dependencies breadth first. However, v8 evaluates - // the source code depth-first. We prioritize module evaluation as it is performed sequentially, - // thus modules are ordered depth-first within the eszip. Except: - // - npm package's meta-modules are loaded sync during referrer loading, therefore they have - // priority over the rest of the referrer dependencies - // - npm cjs modules are loaded at the main module evaluation phase, after module loading - // - dynamic imports are loaded at runtime, if ever - while let Some(module) = to_visit_npm_meta - .pop_front() - .or_else(|| to_visit.pop()) - .or_else(|| to_visit_npm.pop_front()) - .or_else(|| to_visit_dynamic.pop_front()) - { - let dependencies = visit_module( - &opts.graph, - opts.module_kind_resolver, - opts.parser, - &opts.transpile_options, - &emit_options, - &mut modules, - module, - opts.relative_file_base, - npm_packages.as_mut(), - &opts.npm_snapshot, - )?; - if let Some(dependencies) = dependencies { - let mut level_deps = Vec::new(); - for module in dependencies { - if module.is_dynamic() { - to_visit_dynamic.push_back(module); - } else if module.specifier().scheme() == "npm" { - to_visit_npm_meta.push_back(ToVisit::PackageMeta { - module_specifier: module.specifier(), - }); - to_visit_npm.push_back(ToVisit::Package { - module_specifier: module.specifier(), - }); - } else { - level_deps.push(module); - } - } - to_visit.extend(level_deps.into_iter().rev()); - } - } - - for (specifier, target) in &opts.graph.redirects { - let module = EszipV2Module::Redirect { - target: target.to_string(), - }; - let specifier_key = - resolve_specifier_key(specifier, opts.relative_file_base)?; - modules.insert(specifier_key.into_owned(), module); - } - - if let Some(npm_packages) = &mut npm_packages { - // Add the remaining npm packages (those not imported with npm specifiers) at the end of the eszip - for module in npm_packages.drain() { - modules.insert( - module.specifier, - EszipV2Module::Module { - kind: ModuleKind::OpaqueData, - source: EszipV2SourceSlot::Ready(module.source.into()), - source_map: EszipV2SourceSlot::Ready(Arc::new([])), - }, - ); - } - } - - Ok(Self { - modules: EszipV2Modules(Arc::new(Mutex::new(modules))), - npm_snapshot: Some(opts.npm_snapshot), - options: Options::default(), - }) - } - - /// Get the module metadata for a given module specifier. This function will - /// follow redirects. The returned module has functions that can be used to - /// obtain the module source and source map. The module returned from this - /// function is guaranteed to be a valid module, which can be loaded into v8. - /// - /// Note that this function should be used to obtain a module; if you wish to - /// get an import map, use [`get_import_map`](Self::get_import_map) instead. - pub fn get_module(&self, specifier: &str) -> Option { - let module = self.lookup(specifier)?; - - // JSONC is contained in this eszip only for use as an import map. In - // order for the caller to get this JSONC, call `get_import_map` instead. - if module.kind == ModuleKind::Jsonc { - return None; - } - - Some(module) - } - - /// Get the import map for a given specifier. - /// - /// Note that this function should be used to obtain an import map; the returned - /// "Module" is not necessarily a valid module that can be loaded into v8 (in - /// other words, JSONC may be returned). If you wish to get a valid module, - /// use [`get_module`](Self::get_module) instead. - pub fn get_import_map(&self, specifier: &str) -> Option { - let import_map = self.lookup(specifier)?; - - // Import map must be either JSON or JSONC (but JSONC is a special case; - // it's allowed when embedded in a Deno's config file) - if !matches!( - import_map.kind, - ModuleKind::Json | ModuleKind::Jsonc | ModuleKind::OpaqueData - ) { - return None; - } - - Some(import_map) - } - - fn lookup(&self, specifier: &str) -> Option { - let mut specifier = specifier; - let mut visited = HashSet::new(); - let modules = self.modules.0.lock().unwrap(); - loop { - visited.insert(specifier); - let module = modules.get(specifier)?; - match module { - EszipV2Module::Module { kind, .. } => { - return Some(Module { - specifier: specifier.to_string(), - kind: *kind, - inner: ModuleInner::V2(self.modules.clone()), - }); - } - EszipV2Module::Redirect { target } => { - specifier = target; - if visited.contains(specifier) { - return None; - } - } - } - } - } - - /// Returns a list of all the module specifiers in this eszip archive. - pub fn specifiers(&self) -> Vec { - let modules = self.modules.0.lock().unwrap(); - modules.keys().cloned().collect() - } -} - -/// Get an iterator over all the modules (including an import map, if any) in -/// this eszip archive. -/// -/// Note that the iterator will iterate over the specifiers' "snapshot" of the -/// archive. If a new module is added to the archive after the iterator is -/// created via `into_iter()`, that module will not be iterated over. -impl IntoIterator for EszipV2 { - type Item = (String, Module); - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - let specifiers = self.specifiers(); - let mut v = Vec::with_capacity(specifiers.len()); - for specifier in specifiers { - let Some(module) = self.lookup(&specifier) else { - continue; - }; - v.push((specifier, module)); - } - - v.into_iter() - } -} - -async fn read_npm_section( - reader: &mut futures::io::BufReader, - options: Options, - npm_specifiers: HashMap, -) -> Result, ParseError> { - let snapshot = Section::read(reader, options).await?; - if !snapshot.is_checksum_valid() { - return Err(ParseError::InvalidV2NpmSnapshotHash); - } - let original_bytes = snapshot.content(); - if original_bytes.is_empty() { - return Ok(None); - } - let mut packages = Vec::new(); - let mut bytes = original_bytes; - while !bytes.is_empty() { - let result = EszipNpmModule::parse(bytes).map_err(|err| { - let offset = original_bytes.len() - bytes.len(); - ParseError::InvalidV2NpmPackageOffset(offset, err) - })?; - bytes = result.0; - packages.push(result.1); - } - let mut pkg_index_to_pkg_id = HashMap::with_capacity(packages.len()); - for (i, pkg) in packages.iter().enumerate() { - let id = NpmPackageId::from_serialized(&pkg.name).map_err(|err| { - ParseError::InvalidV2NpmPackage(pkg.name.clone(), err.into()) - })?; - pkg_index_to_pkg_id.insert(EszipNpmPackageIndex(i as u32), id); - } - let mut final_packages = Vec::with_capacity(packages.len()); - for (i, pkg) in packages.into_iter().enumerate() { - let eszip_id = EszipNpmPackageIndex(i as u32); - let id = pkg_index_to_pkg_id.get(&eszip_id).unwrap(); - let mut dependencies = HashMap::with_capacity(pkg.dependencies.len()); - for (key, pkg_index) in pkg.dependencies { - let id = match pkg_index_to_pkg_id.get(&pkg_index) { - Some(id) => id, - None => { - return Err(ParseError::InvalidV2NpmPackage( - pkg.name, - anyhow::anyhow!("missing index '{}'", pkg_index.0), - )); - } - }; - dependencies.insert(StackString::from_string(key), id.clone()); - } - final_packages.push(SerializedNpmResolutionSnapshotPackage { - id: id.clone(), - system: Default::default(), - dist: Default::default(), - dependencies, - optional_dependencies: Default::default(), - extra: Default::default(), - is_deprecated: false, - has_bin: false, - has_scripts: false, - optional_peer_dependencies: Default::default(), - }); - } - let mut root_packages = HashMap::with_capacity(npm_specifiers.len()); - for (req, pkg_index) in npm_specifiers { - let id = match pkg_index_to_pkg_id.get(&pkg_index) { - Some(id) => id, - None => { - return Err(ParseError::InvalidV2NpmPackageReq( - req, - anyhow::anyhow!("missing index '{}'", pkg_index.0), - )); - } - }; - let req = PackageReq::from_str(&req) - .map_err(|err| ParseError::InvalidV2NpmPackageReq(req, err.into()))?; - root_packages.insert(req, id.clone()); - } - Ok(Some( - SerializedNpmResolutionSnapshot { - packages: final_packages, - root_packages, - } - // this is ok because we have already verified that all the - // identifiers found in the snapshot are valid via the - // eszip npm package id -> npm package id mapping - .into_valid_unsafe(), - )) -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -struct EszipNpmPackageIndex(u32); - -impl EszipNpmPackageIndex { - pub fn parse(input: &[u8]) -> std::io::Result<(&[u8], Self)> { - let (input, pkg_index) = parse_u32(input)?; - Ok((input, EszipNpmPackageIndex(pkg_index))) - } -} - -struct EszipNpmModule { - name: String, - dependencies: HashMap, -} - -impl EszipNpmModule { - pub fn parse(input: &[u8]) -> std::io::Result<(&[u8], EszipNpmModule)> { - let (input, name) = parse_string(input)?; - let (input, dep_size) = parse_u32(input)?; - let mut deps = HashMap::with_capacity(dep_size as usize); - let mut input = input; - for _ in 0..dep_size { - let parsed_dep = EszipNpmDependency::parse(input)?; - input = parsed_dep.0; - let dep = parsed_dep.1; - deps.insert(dep.0, dep.1); - } - Ok(( - input, - EszipNpmModule { - name, - dependencies: deps, - }, - )) - } -} - -struct EszipNpmDependency(String, EszipNpmPackageIndex); - -impl EszipNpmDependency { - pub fn parse(input: &[u8]) -> std::io::Result<(&[u8], Self)> { - let (input, name) = parse_string(input)?; - let (input, pkg_index) = EszipNpmPackageIndex::parse(input)?; - Ok((input, EszipNpmDependency(name, pkg_index))) - } -} - -fn parse_string(input: &[u8]) -> std::io::Result<(&[u8], String)> { - let (input, size) = parse_u32(input)?; - let (input, name) = move_bytes(input, size as usize)?; - let text = String::from_utf8(name.to_vec()).map_err(|_| { - std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid utf-8 data") - })?; - Ok((input, text)) -} - -fn parse_u32(input: &[u8]) -> std::io::Result<(&[u8], u32)> { - let (input, value_bytes) = move_bytes(input, 4)?; - let value = u32::from_be_bytes(value_bytes.try_into().unwrap()); - Ok((input, value)) -} - -fn move_bytes( - bytes: &[u8], - len: usize, -) -> Result<(&[u8], &[u8]), std::io::Error> { - if bytes.len() < len { - Err(std::io::Error::new( - std::io::ErrorKind::UnexpectedEof, - "unexpected end of bytes", - )) - } else { - Ok((&bytes[len..], &bytes[..len])) - } -} - -#[derive(Debug)] -struct Section(Vec, Options); - -impl Section { - /// Reads a section that's defined as: - /// Size (4) | Body (n) | Hash (32) - async fn read( - mut reader: R, - options: Options, - ) -> Result { - let len = read_u32(&mut reader).await? as usize; - Section::read_with_size(reader, options, len).await - } - - /// Reads a section that's defined as: - /// Body (n) | Hash (32) - /// Where the `n` size is provided. - async fn read_with_size( - mut reader: R, - options: Options, - len: usize, - ) -> Result { - let checksum_size = options - .checksum_size() - .expect("Checksum size must be known") as usize; - let mut body_and_checksum = vec![0u8; len + checksum_size]; - reader.read_exact(&mut body_and_checksum).await?; - - Ok(Section(body_and_checksum, options)) - } - - fn content(&self) -> &[u8] { - &self.0[..self.content_len()] - } - - fn into_content(mut self) -> Vec { - self.0.truncate(self.content_len()); - self.0 - } - - fn content_len(&self) -> usize { - self.total_len() - - self.1.checksum_size().expect("Checksum size must be known") as usize - } - - fn total_len(&self) -> usize { - self.0.len() - } - - fn checksum_hash(&self) -> &[u8] { - &self.0[self.content_len()..] - } - - fn is_checksum_valid(&self) -> bool { - let Some(checksum) = self.1.checksum else { - // degrade to not checksuming - return true; - }; - let actual_hash = checksum.hash(self.content()); - let expected_hash = self.checksum_hash(); - &*actual_hash == expected_hash - } -} - -async fn read_u32( - mut reader: R, -) -> Result { - let mut buf = [0u8; 4]; - reader.read_exact(&mut buf).await?; - Ok(u32::from_be_bytes(buf)) -} - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - use std::io::Cursor; - use std::path::Path; - use std::sync::Arc; - - use async_trait::async_trait; - use deno_ast::EmitOptions; - use deno_ast::TranspileOptions; - use deno_error::JsErrorBox; - use deno_graph::BuildOptions; - use deno_graph::GraphKind; - use deno_graph::ModuleGraph; - use deno_graph::ModuleSpecifier; - use deno_graph::ast::CapturingModuleAnalyzer; - use deno_graph::source::CacheSetting; - use deno_graph::source::LoadOptions; - use deno_graph::source::LoadResponse; - use deno_graph::source::MemoryLoader; - use deno_graph::source::ResolveError; - use deno_graph::source::Source; - use deno_npm::NpmPackageId; - use deno_npm::resolution::SerializedNpmResolutionSnapshot; - use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage; - use deno_semver::npm::NpmPackageNvReference; - use deno_semver::package::PackageNv; - use deno_semver::package::PackageReq; - use futures::io::AllowStdIo; - use futures::io::BufReader; - use import_map::ImportMap; - use pretty_assertions::assert_eq; - use url::Url; - - use super::Checksum; - use super::ESZIP_V2_2_MAGIC; - use super::EszipV2; - use crate::ModuleKind; - use crate::v2::FromGraphNpmPackages; - - struct FileLoader { - base_dir: String, - } - - macro_rules! assert_matches_file { - ($source:ident, $file:literal) => { - assert_eq!( - String::from_utf8($source.to_vec()).unwrap(), - include_str!($file) - ); - }; - } - - macro_rules! assert_matches_file_bytes { - ($source:ident, $file:literal) => { - assert_eq!($source.to_vec(), include_bytes!($file)); - }; - } - - macro_rules! assert_content_order { - ($bytes:expr, $expected_content:expr) => { - let mut bytes: &[u8] = &$bytes; - let expected_content: &[&[u8]] = $expected_content; - for &expected_content in expected_content { - let mut byte_windows = bytes.windows(expected_content.len()); - let Some(expected_content_pos) = - byte_windows.position(|window| window == expected_content) - else { - panic!( - "expected content not found.\nExpected: {:?} ({})\nRemaining: {:?} ({})", - &expected_content, std::str::from_utf8(&expected_content).unwrap(), - bytes, - String::from_utf8_lossy(bytes) - ); - }; - - bytes = &bytes[expected_content_pos + expected_content.len()..]; - } - } - } - - impl deno_graph::source::Loader for FileLoader { - fn load( - &self, - specifier: &ModuleSpecifier, - _options: LoadOptions, - ) -> deno_graph::source::LoadFuture { - match specifier.scheme() { - "file" => { - let path = format!("{}{}", self.base_dir, specifier.path()); - Box::pin(async move { - let path = Path::new(&path); - let Ok(resolved) = path.canonicalize() else { - return Ok(None); - }; - let source = std::fs::read(&resolved).unwrap(); - let specifier = - resolved.file_name().unwrap().to_string_lossy().to_string(); - let specifier = - Url::parse(&format!("file:///{specifier}")).unwrap(); - Ok(Some(LoadResponse::Module { - content: source.into(), - maybe_headers: None, - mtime: None, - specifier, - })) - }) - } - "data" => { - let result = - deno_graph::source::load_data_url(specifier).map_err(|err| { - deno_graph::source::LoadError::Other(Arc::new( - JsErrorBox::from_err(err), - )) - }); - Box::pin(async move { result }) - } - "npm" => Box::pin(async { Ok(None) }), - _ => unreachable!(), - } - } - } - - #[derive(Debug)] - struct ImportMapResolver(ImportMap); - - impl deno_graph::source::Resolver for ImportMapResolver { - fn resolve( - &self, - specifier: &str, - referrer_range: &deno_graph::Range, - _kind: deno_graph::source::ResolutionKind, - ) -> Result { - self - .0 - .resolve(specifier, &referrer_range.specifier) - .map_err(ResolveError::from_err) - } - } - - macro_rules! mock_npm_resolver { - ($resolver_name:ident { $($req_name:literal),+$(,)?} ) => { - #[derive(Debug)] - struct $resolver_name; - - #[async_trait(?Send)] - impl deno_graph::source::NpmResolver for $resolver_name { - fn load_and_cache_npm_package_info(&self, _: &str) {} - - async fn resolve_pkg_reqs( - &self, - package_reqs: &[PackageReq], - ) -> deno_graph::NpmResolvePkgReqsResult { - deno_graph::NpmResolvePkgReqsResult { - results: package_reqs - .iter() - .map(|req| match &*req.name { - $($req_name => Ok(())),+, - _ => unreachable!(), - }) - .collect(), - dep_graph_result: Ok(()), - } - } - } - } - } - - #[tokio::test] - async fn test_graph_external() { - let roots = vec![ModuleSpecifier::parse("file:///external.ts").unwrap()]; - - struct ExternalLoader; - - impl deno_graph::source::Loader for ExternalLoader { - fn load( - &self, - specifier: &ModuleSpecifier, - options: LoadOptions, - ) -> deno_graph::source::LoadFuture { - if options.in_dynamic_branch { - unreachable!(); - } - let scheme = specifier.scheme(); - if scheme == "extern" { - let specifier = specifier.clone(); - return Box::pin(async move { - Ok(Some(LoadResponse::External { specifier })) - }); - } - assert_eq!(scheme, "file"); - let path = format!("./src/testdata/source{}", specifier.path()); - Box::pin(async move { - let path = Path::new(&path); - let resolved = path.canonicalize().unwrap(); - let source = std::fs::read(&resolved).unwrap(); - let specifier = - resolved.file_name().unwrap().to_string_lossy().to_string(); - let specifier = Url::parse(&format!("file:///{specifier}")).unwrap(); - Ok(Some(LoadResponse::Module { - content: source.into(), - maybe_headers: None, - mtime: None, - specifier, - })) - }) - } - } - - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - graph - .build( - roots, - Vec::new(), - &ExternalLoader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("file:///external.ts").unwrap(); - assert_eq!(module.specifier, "file:///external.ts"); - assert!(eszip.get_module("external:fs").is_none()); - } - - #[tokio::test] - async fn from_graph_redirect() { - let roots = vec![ModuleSpecifier::parse("file:///main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("file:///main.ts").unwrap(); - assert_eq!(module.specifier, "file:///main.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/main.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/emit/main.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - let module = eszip.get_module("file:///a.ts").unwrap(); - assert_eq!(module.specifier, "file:///b.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/b.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/emit/b.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - } - - #[tokio::test] - async fn from_graph_json() { - let roots = vec![ModuleSpecifier::parse("file:///json.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("file:///json.ts").unwrap(); - assert_eq!(module.specifier, "file:///json.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/json.ts"); - let _source_map = module.source_map().await.unwrap(); - assert_eq!(module.kind, ModuleKind::JavaScript); - let module = eszip.get_module("file:///data.json").unwrap(); - assert_eq!(module.specifier, "file:///data.json"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/source/data.json"); - let source_map = module.source_map().await.unwrap(); - assert_eq!(&*source_map, &[0; 0]); - assert_eq!(module.kind, ModuleKind::Json); - } - - #[tokio::test] - async fn from_graph_wasm() { - let roots = vec![ModuleSpecifier::parse("file:///wasm.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("file:///wasm.ts").unwrap(); - assert_eq!(module.specifier, "file:///wasm.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/source/wasm.ts"); - let module = eszip.get_module("file:///math.wasm").unwrap(); - assert_eq!(module.specifier, "file:///math.wasm"); - let source = module.source().await.unwrap(); - assert_matches_file_bytes!(source, "./testdata/source/math.wasm"); - let source_map = module.source_map().await.unwrap(); - assert_eq!(&*source_map, &[0; 0]); - assert_eq!(module.kind, ModuleKind::Wasm); - } - - #[tokio::test] - async fn loads_eszip_with_wasm() { - let file = std::fs::File::open("./src/testdata/wasm.eszip2_3").unwrap(); - let (eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .unwrap(); - fut.await.unwrap(); - let module = eszip.get_module("file:///wasm.ts").unwrap(); - assert_eq!(module.specifier, "file:///wasm.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/source/wasm.ts"); - let module = eszip.get_module("file:///math.wasm").unwrap(); - assert_eq!(module.specifier, "file:///math.wasm"); - let source = module.source().await.unwrap(); - assert_matches_file_bytes!(source, "./testdata/source/math.wasm"); - let source_map = module.source_map().await.unwrap(); - assert_eq!(&*source_map, &[0; 0]); - assert_eq!(module.kind, ModuleKind::Wasm); - } - - #[tokio::test] - async fn from_graph_dynamic() { - let roots = vec![ModuleSpecifier::parse("file:///dynamic.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("file:///dynamic.ts").unwrap(); - assert_eq!(module.specifier, "file:///dynamic.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/dynamic.ts"); - let _source_map = module.source_map().await.unwrap(); - assert_eq!(module.kind, ModuleKind::JavaScript); - let module = eszip.get_module("file:///data.json"); - assert!(module.is_some()); // we include statically analyzable dynamic imports - let mut specifiers = eszip.specifiers(); - specifiers.sort(); - assert_eq!(specifiers, vec!["file:///data.json", "file:///dynamic.ts"]); - } - - #[tokio::test] - async fn from_graph_dynamic_data() { - let roots = - vec![ModuleSpecifier::parse("file:///dynamic_data.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("file:///dynamic_data.ts").unwrap(); - assert_eq!(module.specifier, "file:///dynamic_data.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/dynamic_data.ts"); - } - - #[tokio::test] - async fn from_graph_relative_base() { - let base = ModuleSpecifier::parse("file:///dir/").unwrap(); - let roots = vec![ModuleSpecifier::parse("file:///dir/main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = MemoryLoader::new( - vec![ - ( - "file:///dir/main.ts".to_string(), - Source::Module { - specifier: "file:///dir/main.ts".to_string(), - maybe_headers: None, - content: "import './sub_dir/mod.ts';".to_string(), - }, - ), - ( - "file:///dir/sub_dir/mod.ts".to_string(), - Source::Module { - specifier: "file:///dir/sub_dir/mod.ts".to_string(), - maybe_headers: None, - content: "console.log(1);".to_string(), - }, - ), - ], - vec![], - ); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: Some((&base).into()), - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("main.ts").unwrap(); - assert_eq!(module.specifier, "main.ts"); - let source = module.source().await.unwrap(); - assert_eq!( - String::from_utf8_lossy(&source), - "import './sub_dir/mod.ts';\n" - ); - let module = eszip.get_module("sub_dir/mod.ts").unwrap(); - assert_eq!(module.specifier, "sub_dir/mod.ts"); - let source_map = module.source_map().await.unwrap(); - let value: serde_json::Value = - serde_json::from_str(&String::from_utf8_lossy(&source_map)).unwrap(); - assert_eq!( - value, - serde_json::json!({ - "version": 3, - "sources": [ - // should be relative - "sub_dir/mod.ts" - ], - "sourcesContent": [ - "console.log(1);" - ], - "names": [], - "mappings": "AAAA,QAAQ,GAAG,CAAC" - }) - ); - } - - #[cfg(windows)] - #[tokio::test] - async fn from_graph_relative_base_windows_different_drives() { - let base = ModuleSpecifier::parse("file:///V:/dir/").unwrap(); - let roots = vec![ModuleSpecifier::parse("file:///V:/dir/main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = MemoryLoader::new( - vec![ - ( - "file:///V:/dir/main.ts".to_string(), - Source::Module { - specifier: "file:///V:/dir/main.ts".to_string(), - maybe_headers: None, - // obviously this wouldn't work if someone put a V: specifier - // here, but nobody should be writing code like this so we - // just do our best effort to keep things working - content: "import 'file:///C:/other_drive/main.ts';".to_string(), - }, - ), - ( - "file:///C:/other_drive/main.ts".to_string(), - Source::Module { - specifier: "file:///C:/other_drive/main.ts".to_string(), - maybe_headers: None, - content: "console.log(1);".to_string(), - }, - ), - ], - vec![], - ); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: Some((&base).into()), - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - let module = eszip.get_module("main.ts").unwrap(); - assert_eq!(module.specifier, "main.ts"); - let source = module.source().await.unwrap(); - assert_eq!( - String::from_utf8_lossy(&source), - "import 'file:///C:/other_drive/main.ts';\n" - ); - let module = eszip.get_module("file:///C:/other_drive/main.ts").unwrap(); - assert_eq!(module.specifier, "file:///C:/other_drive/main.ts"); - } - - #[cfg(feature = "sha256")] - #[tokio::test] - async fn file_format_parse_redirect() { - let file = std::fs::File::open("./src/testdata/redirect.eszip2").unwrap(); - let (eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .unwrap(); - - let test = async move { - let module = eszip.get_module("file:///main.ts").unwrap(); - assert_eq!(module.specifier, "file:///main.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/redirect_data/main.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/redirect_data/main.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - let module = eszip.get_module("file:///a.ts").unwrap(); - assert_eq!(module.specifier, "file:///b.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/redirect_data/b.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/redirect_data/b.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - - Ok(()) - }; - - tokio::try_join!(fut, test).unwrap(); - } - - #[cfg(feature = "sha256")] - #[tokio::test] - async fn file_format_parse_json() { - let file = std::fs::File::open("./src/testdata/json.eszip2").unwrap(); - let (eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .unwrap(); - - let test = async move { - let module = eszip.get_module("file:///json.ts").unwrap(); - assert_eq!(module.specifier, "file:///json.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/source/json.ts"); - let _source_map = module.source_map().await.unwrap(); - assert_eq!(module.kind, ModuleKind::JavaScript); - let module = eszip.get_module("file:///data.json").unwrap(); - assert_eq!(module.specifier, "file:///data.json"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/data.json"); - let source_map = module.source_map().await.unwrap(); - assert_eq!(&*source_map, &[0; 0]); - assert_eq!(module.kind, ModuleKind::Json); - - Ok(()) - }; - - tokio::try_join!(fut, test).unwrap(); - } - - #[cfg(feature = "sha256")] - #[tokio::test] - async fn file_format_roundtrippable() { - let file = std::fs::File::open("./src/testdata/redirect.eszip2").unwrap(); - let (eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .unwrap(); - fut.await.unwrap(); - let bytes = eszip.into_bytes(); - insta::assert_debug_snapshot!(bytes); - let cursor = Cursor::new(bytes); - let (eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(cursor))) - .await - .unwrap(); - fut.await.unwrap(); - let module = eszip.get_module("file:///main.ts").unwrap(); - assert_eq!(module.specifier, "file:///main.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/redirect_data/main.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/redirect_data/main.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - let module = eszip.get_module("file:///a.ts").unwrap(); - assert_eq!(module.specifier, "file:///b.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/redirect_data/b.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/redirect_data/b.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - } - - #[tokio::test] - async fn import_map() { - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - let resp = deno_graph::source::Loader::load( - &loader, - &Url::parse("file:///import_map.json").unwrap(), - LoadOptions { - in_dynamic_branch: false, - was_dynamic_root: false, - cache_setting: CacheSetting::Use, - maybe_checksum: None, - }, - ) - .await - .unwrap() - .unwrap(); - let (specifier, content) = match resp { - deno_graph::source::LoadResponse::Module { - specifier, content, .. - } => (specifier, content), - _ => unimplemented!(), - }; - let import_map = import_map::parse_from_json( - specifier.clone(), - core::str::from_utf8(&content).unwrap(), - ) - .unwrap(); - let roots = vec![ModuleSpecifier::parse("file:///mapped.js").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - resolver: Some(&ImportMapResolver(import_map.import_map)), - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let mut eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - eszip.add_import_map(ModuleKind::Json, specifier.to_string(), content); - - let module = eszip.get_module("file:///import_map.json").unwrap(); - assert_eq!(module.specifier, "file:///import_map.json"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/source/import_map.json"); - let source_map = module.source_map().await.unwrap(); - assert_eq!(&*source_map, &[0; 0]); - assert_eq!(module.kind, ModuleKind::Json); - - let module = eszip.get_module("file:///mapped.js").unwrap(); - assert_eq!(module.specifier, "file:///mapped.js"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/source/mapped.js"); - let source_map = module.source_map().await.unwrap(); - assert_eq!(&*source_map, &[0; 0]); - assert_eq!(module.kind, ModuleKind::JavaScript); - - let module = eszip.get_module("file:///a.ts").unwrap(); - assert_eq!(module.specifier, "file:///b.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/b.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/emit/b.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - } - - // https://github.com/denoland/eszip/issues/110 - #[tokio::test] - async fn import_map_imported_from_program() { - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - let resp = deno_graph::source::Loader::load( - &loader, - &Url::parse("file:///import_map.json").unwrap(), - LoadOptions { - in_dynamic_branch: false, - was_dynamic_root: false, - cache_setting: CacheSetting::Use, - maybe_checksum: None, - }, - ) - .await - .unwrap() - .unwrap(); - let (specifier, content) = match resp { - deno_graph::source::LoadResponse::Module { - specifier, content, .. - } => (specifier, content), - _ => unimplemented!(), - }; - let import_map = import_map::parse_from_json( - specifier.clone(), - core::str::from_utf8(&content).unwrap(), - ) - .unwrap(); - let roots = - // This file imports `import_map.json` as a module. - vec![ModuleSpecifier::parse("file:///import_import_map.js").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - resolver: Some(&ImportMapResolver(import_map.import_map)), - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let mut eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - eszip.add_import_map(ModuleKind::Json, specifier.to_string(), content); - - // Verify that the resulting eszip consists of two unique modules even - // though `import_map.json` is referenced twice: - // 1. imported from JS - // 2. specified as the import map - assert_eq!( - eszip.specifiers(), - vec![ - "file:///import_map.json".to_string(), - "file:///import_import_map.js".to_string(), - ] - ); - } - - #[tokio::test] - async fn deno_jsonc_as_import_map() { - let loader = FileLoader { - base_dir: "./src/testdata/deno_jsonc_as_import_map".to_string(), - }; - let resp = deno_graph::source::Loader::load( - &loader, - &Url::parse("file:///deno.jsonc").unwrap(), - LoadOptions { - in_dynamic_branch: false, - was_dynamic_root: false, - cache_setting: CacheSetting::Use, - maybe_checksum: None, - }, - ) - .await - .unwrap() - .unwrap(); - let (specifier, content) = match resp { - deno_graph::source::LoadResponse::Module { - specifier, content, .. - } => (specifier, content), - _ => unimplemented!(), - }; - let import_map = import_map::parse_from_value( - specifier.clone(), - jsonc_parser::parse_to_serde_value( - core::str::from_utf8(&content).unwrap(), - &Default::default(), - ) - .unwrap() - .unwrap(), - ) - .unwrap(); - let roots = vec![ModuleSpecifier::parse("file:///main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - resolver: Some(&ImportMapResolver(import_map.import_map)), - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let mut eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - eszip.add_import_map(ModuleKind::Jsonc, specifier.to_string(), content); - - assert_eq!( - eszip.specifiers(), - vec![ - "file:///deno.jsonc".to_string(), - "file:///main.ts".to_string(), - "file:///a.ts".to_string(), - ], - ); - - // JSONC can be obtained by calling `get_import_map` - let deno_jsonc = eszip.get_import_map("file:///deno.jsonc").unwrap(); - let source = deno_jsonc.source().await.unwrap(); - assert_matches_file!( - source, - "./testdata/deno_jsonc_as_import_map/deno.jsonc" - ); - - // JSONC can NOT be obtained as a module - assert!(eszip.get_module("file:///deno.jsonc").is_none()); - } - - #[tokio::test] - async fn eszipv2_iterator_yields_all_modules() { - let loader = FileLoader { - base_dir: "./src/testdata/deno_jsonc_as_import_map".to_string(), - }; - let resp = deno_graph::source::Loader::load( - &loader, - &Url::parse("file:///deno.jsonc").unwrap(), - LoadOptions { - in_dynamic_branch: false, - was_dynamic_root: false, - cache_setting: CacheSetting::Use, - maybe_checksum: None, - }, - ) - .await - .unwrap() - .unwrap(); - let (specifier, content) = match resp { - deno_graph::source::LoadResponse::Module { - specifier, content, .. - } => (specifier, content), - _ => unimplemented!(), - }; - let import_map = import_map::parse_from_value( - specifier.clone(), - jsonc_parser::parse_to_serde_value( - core::str::from_utf8(&content).unwrap(), - &Default::default(), - ) - .unwrap() - .unwrap(), - ) - .unwrap(); - let roots = vec![ModuleSpecifier::parse("file:///main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - resolver: Some(&ImportMapResolver(import_map.import_map)), - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let mut eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - eszip.add_import_map(ModuleKind::Jsonc, specifier.to_string(), content); - - struct Expected { - specifier: String, - source: &'static str, - kind: ModuleKind, - } - - let expected = vec![ - Expected { - specifier: "file:///deno.jsonc".to_string(), - source: include_str!("testdata/deno_jsonc_as_import_map/deno.jsonc"), - kind: ModuleKind::Jsonc, - }, - Expected { - specifier: "file:///main.ts".to_string(), - source: include_str!("testdata/deno_jsonc_as_import_map/main.ts"), - kind: ModuleKind::JavaScript, - }, - Expected { - specifier: "file:///a.ts".to_string(), - source: include_str!("testdata/deno_jsonc_as_import_map/a.ts"), - kind: ModuleKind::JavaScript, - }, - ]; - - for (got, expected) in eszip.into_iter().zip(expected) { - let (got_specifier, got_module) = got; - - assert_eq!(got_specifier, expected.specifier); - assert_eq!(got_module.kind, expected.kind); - assert_eq!( - String::from_utf8_lossy(&got_module.source().await.unwrap()), - expected.source - ); - } - } - - #[tokio::test] - async fn npm_packages() { - let roots = vec![ModuleSpecifier::parse("file:///main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let original_snapshot = SerializedNpmResolutionSnapshot { - root_packages: root_pkgs(&[ - ("package@^1.2", "package@1.2.2"), - ("package@^1", "package@1.2.2"), - ("d@5", "d@5.0.0"), - ]), - packages: Vec::from([ - new_package("package@1.2.2", &[("a", "a@2.2.3"), ("b", "b@1.2.3")]), - new_package("a@2.2.3", &[]), - new_package("b@1.2.3", &[("someotherspecifier", "c@1.1.1")]), - new_package("c@1.1.1", &[]), - new_package("d@5.0.0", &[("e", "e@6.0.0")]), - new_package("e@6.0.0", &[("d", "d@5.0.0")]), - ]), - } - .into_valid() - .unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: original_snapshot.clone(), - }) - .unwrap(); - let bytes = eszip.into_bytes(); - insta::assert_debug_snapshot!(bytes); - let cursor = Cursor::new(bytes); - let (mut eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(cursor))) - .await - .unwrap(); - let snapshot = eszip.take_npm_snapshot().unwrap(); - assert!(eszip.take_npm_snapshot().is_none()); - assert_eq!(snapshot.into_serialized(), { - let mut original = original_snapshot.into_serialized(); - // this will be sorted for determinism - original.packages.sort_by(|a, b| a.id.cmp(&b.id)); - original - }); - - // ensure the eszip still works otherwise - fut.await.unwrap(); - let module = eszip.get_module("file:///main.ts").unwrap(); - assert_eq!(module.specifier, "file:///main.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/main.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/emit/main.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - let module = eszip.get_module("file:///a.ts").unwrap(); - assert_eq!(module.specifier, "file:///b.ts"); - let source = module.source().await.unwrap(); - assert_matches_file!(source, "./testdata/emit/b.ts"); - let source_map = module.source_map().await.unwrap(); - assert_matches_file!(source_map, "./testdata/emit/b.ts.map"); - assert_eq!(module.kind, ModuleKind::JavaScript); - } - - #[cfg(feature = "sha256")] - #[tokio::test] - async fn npm_packages_loaded_file() { - // packages - let file = - std::fs::File::open("./src/testdata/npm_packages.eszip2_1").unwrap(); - let (mut eszip, _) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .unwrap(); - let npm_packages = eszip.take_npm_snapshot().unwrap(); - let expected_snapshot = SerializedNpmResolutionSnapshot { - root_packages: root_pkgs(&[ - ("package@^1.2", "package@1.2.2"), - ("package@^1", "package@1.2.2"), - ("d@5", "d@5.0.0"), - ]), - packages: Vec::from([ - new_package("package@1.2.2", &[("a", "a@2.2.3"), ("b", "b@1.2.3")]), - new_package("a@2.2.3", &[("b", "b@1.2.3")]), - new_package( - "b@1.2.3", - &[("someotherspecifier", "c@1.1.1"), ("a", "a@2.2.3")], - ), - new_package("c@1.1.1", &[]), - new_package("d@5.0.0", &[]), - ]), - } - .into_valid() - .unwrap(); - assert_eq!( - npm_packages.as_serialized(), - expected_snapshot.as_serialized() - ); - - // no packages - let file = - std::fs::File::open("./src/testdata/no_npm_packages.eszip2_1").unwrap(); - let (mut eszip, _) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .unwrap(); - assert!(eszip.take_npm_snapshot().is_none()); - - // invalid file with one byte changed in the npm snapshot - let file = - std::fs::File::open("./src/testdata/npm_packages_invalid_1.eszip2_1") - .unwrap(); - let err = super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .err() - .unwrap(); - assert_eq!(err.to_string(), "invalid eszip v2.1 npm snapshot hash"); - } - - #[tokio::test] - async fn npm_empty_snapshot() { - let roots = vec![ModuleSpecifier::parse("file:///main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - let original_snapshot = SerializedNpmResolutionSnapshot { - root_packages: root_pkgs(&[]), - packages: Vec::from([]), - } - .into_valid() - .unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: original_snapshot.clone(), - }) - .unwrap(); - let bytes = eszip.into_bytes(); - insta::assert_debug_snapshot!(bytes); - let cursor = Cursor::new(bytes); - let (mut eszip, _) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(cursor))) - .await - .unwrap(); - assert!(eszip.take_npm_snapshot().is_none()); - } - - #[tokio::test] - async fn npm_module_source_included_in_eszip() { - let roots = - vec![ModuleSpecifier::parse("file:///npm_imports_main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - - mock_npm_resolver!( - NpmResolver { - "a", - "d", - "other", - } - ); - - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - npm_resolver: Some(&NpmResolver), - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - - let mut from_graph_npm_packages = FromGraphNpmPackages::new(); - from_graph_npm_packages.add_package( - PackageNv::from_str("a@1.2.2").unwrap(), - [( - "a_1.2.2/package.json", - b"package.json of a@1.2.2".as_slice(), - )], - [ - ( - NpmPackageNvReference::from_str("npm:a@1.2.2/foo").unwrap(), - ("a_1.2.2/foo", b"source code of a@1.2.2/foo".as_slice()), - ), - ( - NpmPackageNvReference::from_str("npm:a@1.2.2/bar").unwrap(), - ("a_1.2.2/bar", b"source code of a@1.2.2/bar"), - ), - ], - ); - from_graph_npm_packages.add_package_with_meta( - PackageNv::from_str("d@5.0.0").unwrap(), - [( - "d_5.0.0/package.json", - b"package.json of d@5.0.0".as_slice(), - )], - [ - ("manifest1:d@5.0.0", b"manifest 1 of d@5.0.0".as_slice()), - ("manifest2:d@5.0.0", b"manifest 2 of d@5.0.0"), - ], - [ - ( - NpmPackageNvReference::from_str("npm:d@5.0.0/foo").unwrap(), - ("d_5.0.0/foo", b"source code of d@5.0.0/foo".as_slice()), - ), - ( - NpmPackageNvReference::from_str("npm:d@5.0.0/bar").unwrap(), - ("d_5.0.0/bar", b"source code of d@5.0.0/bar"), - ), - ], - ); - let npm_snapshot = SerializedNpmResolutionSnapshot { - root_packages: root_pkgs(&[ - ("a@^1.2", "a@1.2.2"), - ("d", "d@5.0.0"), - ("other", "other@99.99.99"), - ]), - packages: Vec::from([ - new_package("a@1.2.2", &[]), - new_package("d@5.0.0", &[]), - new_package("other@99.99.99", &[]), - ]), - } - .into_valid() - .unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: Some(from_graph_npm_packages), - npm_snapshot, - }) - .unwrap(); - - let a_package_json = eszip.get_module("a_1.2.2/package.json").unwrap(); - let a_foo = eszip.get_module("a_1.2.2/foo").unwrap(); - let a_bar = eszip.get_module("a_1.2.2/bar").unwrap(); - let d_package_json = eszip.get_module("d_5.0.0/package.json").unwrap(); - let d_manifest_1 = eszip.get_module("manifest1:d@5.0.0").unwrap(); - let d_manifest_2 = eszip.get_module("manifest2:d@5.0.0").unwrap(); - let d_foo = eszip.get_module("d_5.0.0/foo").unwrap(); - // All packages in FromGraphNpmPackages are included in the eszip. Those not in the graph are included at the end of the eszip - let d_bar = eszip.get_module("d_5.0.0/bar").unwrap(); - // other@99.99.99 is in the graph and the snapshot, but not in the eszip because it was not included in the FromGraphNpmPackages - assert!(eszip.get_module("other_99.99.99/foo").is_none()); - - assert_eq!( - &*a_package_json.source().await.unwrap(), - b"package.json of a@1.2.2" - ); - assert_eq!( - &*a_foo.source().await.unwrap(), - b"source code of a@1.2.2/foo" - ); - assert_eq!( - &*a_bar.source().await.unwrap(), - b"source code of a@1.2.2/bar" - ); - assert_eq!( - &*d_package_json.source().await.unwrap(), - b"package.json of d@5.0.0" - ); - assert_eq!( - &*d_manifest_1.source().await.unwrap(), - b"manifest 1 of d@5.0.0" - ); - assert_eq!( - &*d_manifest_2.source().await.unwrap(), - b"manifest 2 of d@5.0.0" - ); - assert_eq!( - &*d_foo.source().await.unwrap(), - b"source code of d@5.0.0/foo" - ); - assert_eq!( - &*d_bar.source().await.unwrap(), - b"source code of d@5.0.0/bar" - ); - } - - #[tokio::test] - async fn npm_modules_are_included_in_import_order() { - let roots = - vec![ModuleSpecifier::parse("file:///npm_imports_main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - - mock_npm_resolver!( - NpmResolver { - "a", - "d", - "other", - } - ); - - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - npm_resolver: Some(&NpmResolver), - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - - let mut from_graph_npm_packages = FromGraphNpmPackages::new(); - from_graph_npm_packages.add_package( - PackageNv::from_str("a@1.2.2").unwrap(), - [ - ( - "a_1.2.2/package.json", - b"package.json of a@1.2.2".as_slice(), - ), - ( - "a_1.2.2/bar/package.json", - b"package.json of a@1.2.2/bar".as_slice(), - ), - ], - [ - ( - NpmPackageNvReference::from_str("npm:a@1.2.2/foo").unwrap(), - ("a_1.2.2/foo", b"source code of a@1.2.2/foo".as_slice()), - ), - ( - NpmPackageNvReference::from_str("npm:a@1.2.2/bar").unwrap(), - ("a_1.2.2/bar", b"source code of a@1.2.2/bar"), - ), - ], - ); - from_graph_npm_packages.add_package_with_meta( - PackageNv::from_str("d@5.0.0").unwrap(), - [( - "d_5.0.0/package.json", - b"package.json of d@5.0.0".as_slice(), - )], - [ - ("manifest1:d@5.0.0", b"manifest 1 of d@5.0.0".as_slice()), - ("manifest2:d@5.0.0", b"manifest 2 of d@5.0.0"), - ], - [ - ( - NpmPackageNvReference::from_str("npm:d@5.0.0/foo").unwrap(), - ("d_5.0.0/foo", b"source code of d@5.0.0/foo".as_slice()), - ), - ( - NpmPackageNvReference::from_str("npm:d@5.0.0/bar").unwrap(), - ("d_5.0.0/bar", b"source code of d@5.0.0/bar"), - ), - ], - ); - from_graph_npm_packages.add_package( - PackageNv::from_str("z@0.1.2").unwrap(), - [( - "z_0.1.2/package.json", - b"package.json of z@0.1.2".as_slice(), - )], - [( - NpmPackageNvReference::from_str("npm:z@0.1.2/foo").unwrap(), - ("z_0.1.2/foo", b"source code of z@0.1.2/foo".as_slice()), - )], - ); - let npm_snapshot = SerializedNpmResolutionSnapshot { - root_packages: root_pkgs(&[ - ("a@^1.2", "a@1.2.2"), - ("d", "d@5.0.0"), - ("z@0.1.2", "z@0.1.2"), - ("other", "other@99.99.99"), - ]), - packages: Vec::from([ - new_package("a@1.2.2", &[]), - new_package("d@5.0.0", &[]), - new_package("z@0.1.2", &[]), - new_package("other@99.99.99", &[]), - ]), - } - .into_valid() - .unwrap(); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: Some(from_graph_npm_packages), - npm_snapshot, - }) - .unwrap(); - - let eszip_bytes = eszip.into_bytes(); - let expected_content: &[&[u8]] = &[ - // root module: npm_imports_main.ts - b"import \"npm:d/foo\";\nimport \"./npm_imports_submodule.ts\";\nimport \"npm:other\";\nimport \"npm:a@^1.2/foo\";", - // npm meta_modules are loaded eagerly during referrer evaluation - // First import is 'd' - b"manifest 1 of d@5.0.0", - b"manifest 2 of d@5.0.0", - b"package.json of d@5.0.0", - // Then 'a' - b"package.json of a@1.2.2", - b"package.json of a@1.2.2/bar", - // Then other imports are included depth-first - b"import \"npm:a@^1.2/bar\";\nimport \"npm:other/bar\";", - // After esm modules, load imported npm packages depth-first. We don't have a module graph for cjs, - // so best effort is to put all package together. However, packages are still ordered by import - b"source code of d@5.0.0/foo", - b"source code of d@5.0.0/bar", - b"source code of a@1.2.2/foo", - b"source code of a@1.2.2/bar", - // Remaining npm packages are appended at the end of the eszip - b"package.json of z@0.1.2", - b"source code of z@0.1.2/foo", - ]; - assert_content_order!(eszip_bytes, expected_content); - } - - #[tokio::test] - async fn npm_packages_not_in_the_graph_are_included_in_the_order_provided() { - let roots = vec![ModuleSpecifier::parse("file:///main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - - let mut from_graph_npm_packages = FromGraphNpmPackages::new(); - from_graph_npm_packages.add_package_with_meta( - PackageNv::from_str("d@5.0.0").unwrap(), - [( - "d_5.0.0/package.json", - b"package.json of d@5.0.0".as_slice(), - )], - [ - ("manifest1:d@5.0.0", b"manifest 1 of d@5.0.0".as_slice()), - ("manifest2:d@5.0.0", b"manifest 2 of d@5.0.0"), - ], - [ - ( - NpmPackageNvReference::from_str("npm:d@5.0.0/foo").unwrap(), - ("d_5.0.0/foo", b"source code of d@5.0.0/foo".as_slice()), - ), - ( - NpmPackageNvReference::from_str("npm:d@5.0.0/bar").unwrap(), - ("d_5.0.0/bar", b"source code of d@5.0.0/bar"), - ), - ], - ); - from_graph_npm_packages.add_package( - PackageNv::from_str("a@1.2.2").unwrap(), - [( - "a_1.2.2/package.json", - b"package.json of a@1.2.2".as_slice(), - )], - [ - ( - NpmPackageNvReference::from_str("npm:a@1.2.2/foo").unwrap(), - ("a_1.2.2/foo", b"source code of a@1.2.2/foo".as_slice()), - ), - ( - NpmPackageNvReference::from_str("npm:a@1.2.2/bar").unwrap(), - ("a_1.2.2/bar", b"source code of a@1.2.2/bar"), - ), - ], - ); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: Some(from_graph_npm_packages), - npm_snapshot: Default::default(), - }) - .unwrap(); - - let eszip_bytes = eszip.into_bytes(); - let expected_content: &[&[u8]] = &[ - // First import is 'd' - b"manifest 1 of d@5.0.0", - b"manifest 2 of d@5.0.0", - b"package.json of d@5.0.0", - b"source code of d@5.0.0/foo", - b"source code of d@5.0.0/bar", - // Then 'a' - b"package.json of a@1.2.2", - b"source code of a@1.2.2/foo", - b"source code of a@1.2.2/bar", - ]; - assert_content_order!(eszip_bytes, expected_content); - } - - #[tokio::test] - #[ignore = "implementation postponed"] - async fn npm_modules_package_resolution() { - let roots = - vec![ModuleSpecifier::parse("file:///npm_imports_main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - - mock_npm_resolver!( - NpmResolver { - "a", - "d", - "other", - } - ); - - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - npm_resolver: Some(&NpmResolver), - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - - let mut from_graph_npm_packages = FromGraphNpmPackages::new(); - from_graph_npm_packages.add_package( - PackageNv::from_str("other@99.99.99").unwrap(), - [("other/package.json", br#"{"main": "other.js"}"#.as_slice())], - [ - ( - NpmPackageNvReference::from_str("npm:other@99.99.99/other.js") - .unwrap(), - ( - "other/other", - b"source code of other@99.99.99/other.js".as_slice(), - ), - ), - ( - NpmPackageNvReference::from_str("npm:other@99.99.99/bar").unwrap(), - ("other/bar", b"source code of other@99.99.99/bar".as_slice()), - ), - ], - ); - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: Some(from_graph_npm_packages), - npm_snapshot: Default::default(), - }) - .unwrap(); - - let eszip_bytes = eszip.into_bytes(); - - // All npm packages present in FromGraphNpmPackages are included in the eszip. We want to make sure - // the package resolution is able to resolve npm:other => other@99.99.99/other and put the module - // in the order it is loaded - let expected_content: &[&[u8]] = &[ - // root module: npm_imports_main.ts - b"import \"npm:d/foo\";\nimport \"./npm_imports_submodule.ts\";\nimport \"npm:other\";\nimport \"npm:a@^1.2/foo\";", - // npm packages are loaded eagerly during referrer evaluation - br#"{"main": "other.js"}"#, - b"source code of other@99.99.99/other.js", - b"import \"npm:a@^1.2/bar\";\nimport \"npm:other/bar\";", - b"source code of other@99.99.99/bar", - ]; - assert_content_order!(eszip_bytes, expected_content); - } - - #[tokio::test] - async fn into_bytes_sequences_modules_depth_first() { - let roots = vec![ModuleSpecifier::parse("file:///parent.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - - let eszip = super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap(); - - let eszip_bytes = eszip.into_bytes(); - let expected_content: &[&[u8]] = &[ - b"import \"./child1.ts\";\nimport \"./child2.ts\";", - b"import \"./grandchild1.ts\";", - b"export const grandchild1 = \"grandchild1\";", - b"import \"./grandchild2.ts\";", - b"export const grandchild2 = \"grandchild2\";", - ]; - assert_content_order!(eszip_bytes, expected_content); - } - - #[tokio::test] - async fn add_to_front_adds_module_to_the_front_instead_of_the_back() { - let mut eszip = super::EszipV2::default(); - - eszip.add_opaque_data( - String::from("third"), - Arc::from(*b"third source added with add_opaque_data"), - ); - eszip.add_to_front( - ModuleKind::OpaqueData, - String::from("second"), - *b"second source added with add_to_front", - *b"second source map added with add_to_front", - ); - eszip.add_to_front( - ModuleKind::OpaqueData, - String::from("first"), - *b"first source added with add_to_front", - *b"first source map added with add_to_front", - ); - - let eszip_bytes = eszip.into_bytes(); - let expected_content: &[&[u8]] = &[ - b"first source added with add_to_front", - b"second source added with add_to_front", - b"third source added with add_opaque_data", - b"first source map added with add_to_front", - b"second source map added with add_to_front", - ]; - assert_content_order!(eszip_bytes, expected_content); - } - - #[tokio::test] - async fn opaque_data() { - let mut eszip = super::EszipV2::default(); - let opaque_data: Arc<[u8]> = Arc::new([1, 2, 3]); - eszip.add_opaque_data("+s/foobar".to_string(), opaque_data.clone()); - let bytes = eszip.into_bytes(); - insta::assert_debug_snapshot!(bytes); - let cursor = Cursor::new(bytes); - let (eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(cursor))) - .await - .unwrap(); - fut.await.unwrap(); - let opaque_data = eszip.get_module("+s/foobar").unwrap(); - assert_eq!(opaque_data.specifier, "+s/foobar"); - let source = opaque_data.source().await.unwrap(); - assert_eq!(&*source, &[1, 2, 3]); - assert_eq!(opaque_data.kind, ModuleKind::OpaqueData); - } - - #[tokio::test] - async fn v2_2_defaults_to_no_checksum() { - let eszip = main_eszip().await; - let bytes = eszip.into_bytes(); - let (eszip, fut) = super::EszipV2::parse(BufReader::new(bytes.as_slice())) - .await - .unwrap(); - fut.await.unwrap(); - assert_eq!(eszip.options.checksum, Some(super::Checksum::NoChecksum)); - assert!(!eszip.is_checksumed()); - assert!(!eszip.should_be_checksumed()); - } - - #[cfg(feature = "sha256")] - #[tokio::test] - async fn v2_1_and_older_default_to_sha256_checksum() { - let file = std::fs::File::open("./src/testdata/json.eszip2").unwrap(); - let (eszip, fut) = - super::EszipV2::parse(BufReader::new(AllowStdIo::new(file))) - .await - .unwrap(); - fut.await.unwrap(); - assert_eq!(eszip.options.checksum, Some(super::Checksum::Sha256)); - assert_eq!(eszip.options.checksum_size(), Some(32)); - assert!(eszip.is_checksumed()); - } - - #[cfg(feature = "xxhash3")] - #[tokio::test] - async fn v2_2_set_xxhash3_checksum() { - let mut eszip = main_eszip().await; - eszip.set_checksum(super::Checksum::XxHash3); - let main_source = eszip - .get_module("file:///main.ts") - .unwrap() - .source() - .await - .unwrap(); - let bytes = eszip.into_bytes(); - let main_xxhash = xxhash_rust::xxh3::xxh3_64(&main_source).to_be_bytes(); - let xxhash_in_bytes = bytes - .windows(main_xxhash.len()) - .any(|window| window == main_xxhash); - assert!(xxhash_in_bytes); - let (parsed_eszip, fut) = EszipV2::parse(BufReader::new(bytes.as_slice())) - .await - .unwrap(); - fut.await.unwrap(); - assert_eq!( - parsed_eszip.options.checksum, - Some(super::Checksum::XxHash3) - ); - assert!(parsed_eszip.is_checksumed()); - } - - #[tokio::test] - async fn v2_2_options_in_header_are_optional() { - let empty_options = 0_u32.to_be_bytes(); - let bytes = main_eszip().await.into_bytes(); - let existing_options_size = - std::mem::size_of::() + std::mem::size_of::() * 4; - let options_start = ESZIP_V2_2_MAGIC.len(); - // Replace the default options set by the library with an empty options header - let new_bytes = [ - &bytes[..options_start], - empty_options.as_slice(), - &bytes[options_start + existing_options_size..], - ] - .concat(); - let (new_eszip, fut) = EszipV2::parse(BufReader::new(new_bytes.as_slice())) - .await - .unwrap(); - fut.await.unwrap(); - - assert_eq!(new_eszip.options.checksum, Some(Checksum::NoChecksum)); - assert!(!new_eszip.is_checksumed()); - assert!(!new_eszip.should_be_checksumed()); - } - - #[cfg(feature = "sha256")] - #[tokio::test] - #[should_panic] - async fn v2_2_unknown_checksum_function_degrades_to_no_checksum() { - // checksum 255; checksum_size 32 - let option_bytes = &[0, 255, 1, 32]; - let futuristic_options = [ - 4_u32.to_be_bytes().as_slice(), - option_bytes, - ::digest(option_bytes).as_slice(), - ] - .concat(); - let mut eszip = main_eszip().await; - // Using sha256/32Bytes as mock hash. - eszip.set_checksum(Checksum::Sha256); - let bytes = eszip.into_bytes(); - let existing_options_size = std::mem::size_of::() - + std::mem::size_of::() * 4 - + ::output_size(); - let options_start = ESZIP_V2_2_MAGIC.len(); - let new_bytes = [ - &bytes[..options_start], - futuristic_options.as_slice(), - &bytes[options_start + existing_options_size..], - ] - .concat(); - let (new_eszip, fut) = EszipV2::parse(BufReader::new(new_bytes.as_slice())) - .await - .unwrap(); - fut.await.unwrap(); - - assert_eq!(new_eszip.options.checksum, None); - assert_eq!(new_eszip.options.checksum_size(), Some(32)); - assert!(!new_eszip.is_checksumed()); - assert!(new_eszip.should_be_checksumed()); - - // This should panic, as cannot re-encode without setting an explicit checksum configuration - new_eszip.into_bytes(); - } - - #[cfg(feature = "sha256")] - #[tokio::test] - async fn wrong_checksum() { - let mut eszip = main_eszip().await; - eszip.set_checksum(Checksum::Sha256); - let main_source = eszip - .get_module("file:///main.ts") - .unwrap() - .source() - .await - .unwrap(); - let bytes = eszip.into_bytes(); - let mut main_sha256 = ::digest(&main_source); - let sha256_in_bytes_start = bytes - .windows(main_sha256.len()) - .position(|window| window == &*main_sha256) - .unwrap(); - main_sha256.reverse(); - let bytes = [ - &bytes[..sha256_in_bytes_start], - main_sha256.as_slice(), - &bytes[sha256_in_bytes_start + main_sha256.len()..], - ] - .concat(); - let (_eszip, fut) = EszipV2::parse(BufReader::new(bytes.as_slice())) - .await - .unwrap(); - let result = fut.await; - assert!(result.is_err()); - assert!(matches!( - result, - Err(crate::error::ParseError::InvalidV2SourceHash(_)) - )); - } - - #[tokio::test] - async fn v2_2_options_forward_compatibility() { - let option_bytes = &[255; 98]; - let futuristic_options = - [98_u32.to_be_bytes().as_slice(), option_bytes].concat(); - let bytes = main_eszip().await.into_bytes(); - let existing_options_size = - std::mem::size_of::() + std::mem::size_of::() * 4; - let options_start = ESZIP_V2_2_MAGIC.len(); - let new_bytes = [ - &bytes[..options_start], - futuristic_options.as_slice(), - &bytes[options_start + existing_options_size..], - ] - .concat(); - // Assert that unknown options are ignored just fine - let (_new_eszip, fut) = - EszipV2::parse(BufReader::new(new_bytes.as_slice())) - .await - .unwrap(); - fut.await.unwrap(); - } - - fn root_pkgs(pkgs: &[(&str, &str)]) -> HashMap { - pkgs - .iter() - .map(|(key, value)| { - ( - PackageReq::from_str(key).unwrap(), - NpmPackageId::from_serialized(value).unwrap(), - ) - }) - .collect() - } - - fn new_package( - id: &str, - deps: &[(&str, &str)], - ) -> SerializedNpmResolutionSnapshotPackage { - SerializedNpmResolutionSnapshotPackage { - id: NpmPackageId::from_serialized(id).unwrap(), - dependencies: deps - .iter() - .map(|(key, value)| { - ( - deno_semver::StackString::from_str(key), - NpmPackageId::from_serialized(value).unwrap(), - ) - }) - .collect(), - system: Default::default(), - dist: Default::default(), - optional_dependencies: Default::default(), - extra: Default::default(), - is_deprecated: false, - has_bin: false, - has_scripts: false, - optional_peer_dependencies: Default::default(), - } - } - - async fn main_eszip() -> EszipV2 { - let roots = vec![ModuleSpecifier::parse("file:///main.ts").unwrap()]; - let analyzer = CapturingModuleAnalyzer::default(); - let mut graph = ModuleGraph::new(GraphKind::CodeOnly); - let loader = FileLoader { - base_dir: "./src/testdata/source".to_string(), - }; - graph - .build( - roots, - Vec::new(), - &loader, - BuildOptions { - module_analyzer: &analyzer, - ..Default::default() - }, - ) - .await; - graph.valid().unwrap(); - super::EszipV2::from_graph(super::FromGraphOptions { - graph, - module_kind_resolver: Default::default(), - parser: analyzer.as_capturing_parser(), - transpile_options: TranspileOptions::default(), - emit_options: EmitOptions::default(), - relative_file_base: None, - npm_packages: None, - npm_snapshot: Default::default(), - }) - .unwrap() - } -}