├── .dockerignore ├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── Dockerfile ├── README.md ├── fly.production.toml ├── formatter ├── .cargo-ok ├── .dockerignore ├── .gitignore ├── Cargo.toml ├── Dockerfile ├── LICENSE_APACHE ├── LICENSE_MIT ├── README.md └── src │ └── lib.rs ├── frontend ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── public │ └── global.css ├── src │ ├── ActionButton.svelte │ ├── App.svelte │ ├── ButtonPanel.svelte │ ├── Editor.svelte │ ├── Error.svelte │ ├── Output.svelte │ ├── assets │ │ ├── some.css │ │ └── svelte.png │ ├── code.ts │ ├── const.ts │ ├── loading.ts │ ├── main.ts │ ├── response.ts │ └── vite-env.d.ts ├── svelte.config.js ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── justfile ├── md └── about.md ├── server ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── public │ ├── about.md │ ├── assets │ │ ├── formatter_bg.1471ca7a.wasm │ │ ├── index.5ce90726.js │ │ └── index.75371d95.css │ ├── global.css │ └── index.html └── src │ ├── error.rs │ ├── handler.rs │ ├── main.rs │ ├── static_server.rs │ ├── telemetry.rs │ └── wasm.rs └── templates └── base.html /.dockerignore: -------------------------------------------------------------------------------- 1 | frontend 2 | **/node_modules 3 | **/target 4 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to fly.io (production) 2 | 3 | on: workflow_dispatch 4 | 5 | env: 6 | FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} 7 | 8 | jobs: 9 | deploy: 10 | name: deploy 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v3 15 | 16 | - uses: actions/cache@v3 17 | with: 18 | path: /tmp/.buildx-cache 19 | key: ${{ runner.os }}-buildx-${{ github.sha }} 20 | restore-keys: | 21 | ${{ runner.os }}-buildx- 22 | 23 | - name: Set up Docker Buildx 24 | id: buildx 25 | uses: docker/setup-buildx-action@v2 26 | 27 | - uses: extractions/setup-just@v1 28 | - run: just build-frontend-ci 29 | 30 | # - name: Build image 31 | # uses: docker/build-push-action@v3 32 | # with: 33 | # context: . 34 | # push: false 35 | # tags: typerust 36 | # load: true 37 | # cache-from: type=local,src=/tmp/.buildx-cache,scope=${{ github.workflow }} 38 | # cache-to: type=local,mode=max,dest=/tmp/.buildx-cache,scope=${{ github.workflow }} 39 | 40 | - uses: superfly/flyctl-actions/setup-flyctl@master 41 | - run: flyctl deploy --config fly.production.toml 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.env 2 | target/ 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:latest as builder 2 | 3 | WORKDIR /server 4 | 5 | # Workaround to avoid rebuilding dependencies every time 6 | COPY server/Cargo.toml Cargo.toml 7 | RUN mkdir -p src 8 | RUN echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs 9 | RUN cargo build --release 10 | RUN rm -f target/release/deps/typerust* 11 | 12 | COPY server . 13 | RUN cargo install --path . 14 | 15 | 16 | FROM rust:slim 17 | WORKDIR /app 18 | 19 | RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates 20 | RUN rustup target add wasm32-wasip1 21 | 22 | COPY --from=builder /usr/local/cargo/bin/typerust . 23 | COPY templates templates 24 | 25 | EXPOSE 8080 26 | 27 | ENTRYPOINT ["./typerust"] 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Rust playground 2 | Welcome to **TypeRust**! This is a simple Rust playground where you can build or run your Rust code and share it with others. 3 | 4 | There are a few things to keep in mind before using it: 5 | * Code execution time is limited and if it takes too long to complete it will be interrupted. 6 | * Your program cannot use too much memory. If it exceeds the limit it will be interrupted. 7 | * Since the program runs in a sandbox, it doesn't have access to filesystem and/or network. Of course simply building code is fine. 8 | 9 | ## Environment 10 | 11 | * The code is compiled to `wasm32-wasi` target and is run in a [`wasmtime`](https://github.com/bytecodealliance/wasmtime) instance. 12 | * The latest stable version of Rust with 2021 edition is used. 13 | * There is no way to install crates (yet). 14 | 15 | ## Development 16 | 17 | ### Tech 18 | TypeRust playground is powered by [`Svelte`](https://svelte.dev/) and [CodeMirror](https://codemirror.net/6/) editor on frontend and [`axum`](https://github.com/tokio-rs/axum) (and its ecosystem) on backend. [`wasmtime`](https://github.com/bytecodealliance/wasmtime) is used to create ephemeral WASM virtual machines to run user code. The whole thing is deployed to [Fly.io](https://fly.io/). 19 | 20 | ### Source code 21 | You can find source code on Github: [https://github.com/jlkiri/typerust](https://github.com/jlkiri/typerust). 22 | 23 | ## About the author 24 | This playground was created by [Kirill Vasiltsov](https://www.kirillvasiltsov.com/). 25 | 26 | ### Sponsorship 27 | Currently I (the author) pay for the infrastructure out of my own pocket. It is not much but any help is appreciated. Sponsoring via Github is not available at the moment, but you can use my [PayPal profile](https://paypal.me/jlkiri) if you want to help. Anyone with one-time payment of 10$ or more gets: 28 | 29 | * A huge Thank You from me 30 | * Optional advice on working as a software engineer in Japan 31 | * Optional advice on contributing to OSS projects 32 | 33 | To receive advice contact me at email address on my [personal homepage](https://www.kirillvasiltsov.com/). 34 | -------------------------------------------------------------------------------- /fly.production.toml: -------------------------------------------------------------------------------- 1 | # fly.toml file generated for rustplayground on 2022-05-21T20:34:49+09:00 2 | 3 | app = "typerust" 4 | 5 | kill_signal = "SIGINT" 6 | kill_timeout = 5 7 | processes = [] 8 | 9 | [env] 10 | RUST_LOG = "info" 11 | IP_ADDR = "0.0.0.0:8080" 12 | OTLP_EXPORT_URL = "https://api.honeycomb.io:443" 13 | LOCAL_LOG_ONLY = "false" 14 | 15 | [experimental] 16 | allowed_public_ports = [] 17 | auto_rollback = true 18 | 19 | [http_service] 20 | internal_port = 8080 21 | # force_https = true 22 | auto_stop_machines = "stop" 23 | auto_start_machines = true 24 | min_machines_running = 0 25 | [http_service.concurrency] 26 | type = "requests" 27 | soft_limit = 200 28 | hard_limit = 250 29 | -------------------------------------------------------------------------------- /formatter/.cargo-ok: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlkiri/typerust/7350ea55a205bf931c50640b802b083908b6cdd6/formatter/.cargo-ok -------------------------------------------------------------------------------- /formatter/.dockerignore: -------------------------------------------------------------------------------- 1 | **/target 2 | -------------------------------------------------------------------------------- /formatter/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | wasm-pack.log 7 | -------------------------------------------------------------------------------- /formatter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "formatter" 3 | version = "0.1.0" 4 | authors = ["jlkiri "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2.63" 12 | 13 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 14 | # compared to the default allocator's ~10K. It is slower than the default 15 | # allocator, however. 16 | # 17 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 18 | wee_alloc = { version = "0.4.5" } 19 | prettyplease = "0.1.11" 20 | syn = { version = "1.0.96", default-features = false, features = [ 21 | "parsing", 22 | "full", 23 | ] } 24 | 25 | [dev-dependencies] 26 | wasm-bindgen-test = "0.3.13" 27 | 28 | [profile.release] 29 | # Tell `rustc` to optimize for small code size. 30 | opt-level = "s" 31 | -------------------------------------------------------------------------------- /formatter/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:latest as builder 2 | 3 | WORKDIR /formatter 4 | 5 | # Install wasm-pack 6 | RUN curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh 7 | 8 | # Workaround to avoid rebuilding dependencies every time 9 | COPY Cargo.toml Cargo.toml 10 | RUN mkdir -p src 11 | RUN touch src/lib.rs 12 | RUN rustup target add wasm32-unknown-unknown 13 | RUN cargo build --release --target wasm32-unknown-unknown 14 | RUN rm -f target/wasm32-unknown-unknown/deps/formatter* 15 | 16 | COPY . . 17 | RUN wasm-pack build --release --target web 18 | 19 | FROM scratch 20 | 21 | COPY --from=builder /formatter/pkg . 22 | -------------------------------------------------------------------------------- /formatter/LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /formatter/LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 jlkiri 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /formatter/README.md: -------------------------------------------------------------------------------- 1 | ## Formatter 2 | 3 | ``` 4 | wasm-pack build --release --target web 5 | ``` 6 | -------------------------------------------------------------------------------- /formatter/src/lib.rs: -------------------------------------------------------------------------------- 1 | use prettyplease; 2 | use syn; 3 | use wasm_bindgen::prelude::*; 4 | 5 | // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global 6 | // allocator. 7 | #[global_allocator] 8 | static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; 9 | 10 | #[wasm_bindgen] 11 | pub fn pretty(code: String) -> String { 12 | let syntax_tree = syn::parse_file(&code).unwrap(); 13 | let formatted = prettyplease::unparse(&syntax_tree); 14 | formatted 15 | } 16 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /frontend/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["svelte.svelte-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Svelte + TS + Vite 2 | 3 | This template should help get you started developing with Svelte and TypeScript in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). 8 | 9 | ## Need an official Svelte framework? 10 | 11 | Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more. 12 | 13 | ## Technical considerations 14 | 15 | **Why use this over SvelteKit?** 16 | 17 | - It brings its own routing solution which might not be preferable for some users. 18 | - It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app. 19 | `vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example. 20 | 21 | This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project. 22 | 23 | Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate. 24 | 25 | **Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?** 26 | 27 | Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information. 28 | 29 | **Why include `.vscode/extensions.json`?** 30 | 31 | Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project. 32 | 33 | **Why enable `allowJs` in the TS template?** 34 | 35 | While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant. 36 | 37 | **Why is HMR not preserving my local component state?** 38 | 39 | HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr). 40 | 41 | If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR. 42 | 43 | ```ts 44 | // store.ts 45 | // An extremely simple external store 46 | import { writable } from 'svelte/store' 47 | export default writable(0) 48 | ``` 49 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Typerust | Playground 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /frontend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend-next", 3 | "version": "0.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "frontend-next", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "@codemirror/basic-setup": "^0.20.0", 12 | "@codemirror/lang-rust": "^0.20.0", 13 | "@codemirror/theme-one-dark": "^0.20.0", 14 | "@types/lz-string": "^1.3.34", 15 | "@zerodevx/svelte-toast": "^0.7.2", 16 | "formatter": "file:../formatter/pkg", 17 | "lz-string": "^1.4.4", 18 | "svelte-loading-spinners": "^0.1.7" 19 | }, 20 | "devDependencies": { 21 | "@sveltejs/vite-plugin-svelte": "^1.0.0-next.30", 22 | "@tsconfig/svelte": "^2.0.1", 23 | "svelte": "^3.44.0", 24 | "svelte-check": "^2.2.7", 25 | "svelte-preprocess": "^4.9.8", 26 | "tslib": "^2.3.1", 27 | "typescript": "^4.5.4", 28 | "vite": "^2.9.9" 29 | } 30 | }, 31 | "../formatter/pkg": { 32 | "name": "formatter", 33 | "version": "0.1.0" 34 | }, 35 | "node_modules/@codemirror/autocomplete": { 36 | "version": "0.20.0", 37 | "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.20.0.tgz", 38 | "integrity": "sha512-F6VOM8lImn5ApqxJcaWgdl7hhlw8B5yAfZJGlsQifcpNotkZOMND61mBFZ84OmSLWxtT8/smkSeLvJupKbjP9w==", 39 | "dependencies": { 40 | "@codemirror/language": "^0.20.0", 41 | "@codemirror/state": "^0.20.0", 42 | "@codemirror/view": "^0.20.0", 43 | "@lezer/common": "^0.16.0" 44 | } 45 | }, 46 | "node_modules/@codemirror/basic-setup": { 47 | "version": "0.20.0", 48 | "resolved": "https://registry.npmjs.org/@codemirror/basic-setup/-/basic-setup-0.20.0.tgz", 49 | "integrity": "sha512-W/ERKMLErWkrVLyP5I8Yh8PXl4r+WFNkdYVSzkXYPQv2RMPSkWpr2BgggiSJ8AHF/q3GuApncDD8I4BZz65fyg==", 50 | "dependencies": { 51 | "@codemirror/autocomplete": "^0.20.0", 52 | "@codemirror/commands": "^0.20.0", 53 | "@codemirror/language": "^0.20.0", 54 | "@codemirror/lint": "^0.20.0", 55 | "@codemirror/search": "^0.20.0", 56 | "@codemirror/state": "^0.20.0", 57 | "@codemirror/view": "^0.20.0" 58 | } 59 | }, 60 | "node_modules/@codemirror/commands": { 61 | "version": "0.20.0", 62 | "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-0.20.0.tgz", 63 | "integrity": "sha512-v9L5NNVA+A9R6zaFvaTbxs30kc69F6BkOoiEbeFw4m4I0exmDEKBILN6mK+GksJtvTzGBxvhAPlVFTdQW8GB7Q==", 64 | "dependencies": { 65 | "@codemirror/language": "^0.20.0", 66 | "@codemirror/state": "^0.20.0", 67 | "@codemirror/view": "^0.20.0", 68 | "@lezer/common": "^0.16.0" 69 | } 70 | }, 71 | "node_modules/@codemirror/lang-rust": { 72 | "version": "0.20.0", 73 | "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-0.20.0.tgz", 74 | "integrity": "sha512-H49ONe7TQSD6n9X7je56wEmsE5rPC7vgDxxAoWUEQGQWzIlrQD2gRrfqe4y+dbD/yGVhjWla7UyuyUPQVpGJyg==", 75 | "dependencies": { 76 | "@codemirror/language": "^0.20.0", 77 | "@lezer/rust": "^0.16.0" 78 | } 79 | }, 80 | "node_modules/@codemirror/language": { 81 | "version": "0.20.0", 82 | "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.20.0.tgz", 83 | "integrity": "sha512-lPsF5Y2ZFd5lZ9+7HXTxu57Po3dms3+7q2iAffzrbis2wyJo0lzi/j2312EKStEzwd0pGGpvrUk2dEd333N2jw==", 84 | "dependencies": { 85 | "@codemirror/state": "^0.20.0", 86 | "@codemirror/view": "^0.20.0", 87 | "@lezer/common": "^0.16.0", 88 | "@lezer/highlight": "^0.16.0", 89 | "@lezer/lr": "^0.16.0" 90 | } 91 | }, 92 | "node_modules/@codemirror/lint": { 93 | "version": "0.20.2", 94 | "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-0.20.2.tgz", 95 | "integrity": "sha512-xEH3wlzoFLEhPEeMVRNoQIhoTCMEtXhVxemGh3FYjLfl/CL3B2Wz+CU7ooP5SKhN1le7JqUNSfiTArFP+IzFuw==", 96 | "dependencies": { 97 | "@codemirror/state": "^0.20.0", 98 | "@codemirror/view": "^0.20.2", 99 | "crelt": "^1.0.5" 100 | } 101 | }, 102 | "node_modules/@codemirror/search": { 103 | "version": "0.20.1", 104 | "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-0.20.1.tgz", 105 | "integrity": "sha512-ROe6gRboQU5E4z6GAkNa2kxhXqsGNbeLEisbvzbOeB7nuDYXUZ70vGIgmqPu0tB+1M3F9yWk6W8k2vrFpJaD4Q==", 106 | "dependencies": { 107 | "@codemirror/state": "^0.20.0", 108 | "@codemirror/view": "^0.20.0", 109 | "crelt": "^1.0.5" 110 | } 111 | }, 112 | "node_modules/@codemirror/state": { 113 | "version": "0.20.0", 114 | "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.20.0.tgz", 115 | "integrity": "sha512-R3XrAWCS5Xm9lx+4pDET4EUPEg+8bDfAa5zoOFIhx+VChsfew9Vy33dAjCXS5ES4Q8UecW4WM4UudmUFpZ+86A==" 116 | }, 117 | "node_modules/@codemirror/theme-one-dark": { 118 | "version": "0.20.0", 119 | "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-0.20.0.tgz", 120 | "integrity": "sha512-iqTKaiOZddwlc2rYF+9D60Gfyz9EsSawVejSjyP2FCtOwZ1X0frG5/ByTKH5FBDD2+P7W8+h/OIG4r5dWq4bgA==", 121 | "dependencies": { 122 | "@codemirror/language": "^0.20.0", 123 | "@codemirror/state": "^0.20.0", 124 | "@codemirror/view": "^0.20.0", 125 | "@lezer/highlight": "^0.16.0" 126 | } 127 | }, 128 | "node_modules/@codemirror/view": { 129 | "version": "0.20.4", 130 | "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.20.4.tgz", 131 | "integrity": "sha512-6yprcc0/39EzI6y9Jm/J5F9lFzQik0yj8gE3CO/wOCQ4vd3Drol114mMK91LGtKrfoS0MFKVGulw0TdfN49Bfw==", 132 | "dependencies": { 133 | "@codemirror/state": "^0.20.0", 134 | "style-mod": "^4.0.0", 135 | "w3c-keyname": "^2.2.4" 136 | } 137 | }, 138 | "node_modules/@jridgewell/resolve-uri": { 139 | "version": "3.0.7", 140 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", 141 | "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", 142 | "dev": true, 143 | "engines": { 144 | "node": ">=6.0.0" 145 | } 146 | }, 147 | "node_modules/@jridgewell/sourcemap-codec": { 148 | "version": "1.4.13", 149 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", 150 | "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", 151 | "dev": true 152 | }, 153 | "node_modules/@jridgewell/trace-mapping": { 154 | "version": "0.3.13", 155 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", 156 | "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", 157 | "dev": true, 158 | "dependencies": { 159 | "@jridgewell/resolve-uri": "^3.0.3", 160 | "@jridgewell/sourcemap-codec": "^1.4.10" 161 | } 162 | }, 163 | "node_modules/@lezer/common": { 164 | "version": "0.16.0", 165 | "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.0.tgz", 166 | "integrity": "sha512-H6sPCku+asKWYaNjwfQ1Uvcay9UP1Pdzu4qpy8GtRZ0cKT2AAGnj9MQGiRtY18MDntvhYRJxNGv7FNWOSV/e8A==" 167 | }, 168 | "node_modules/@lezer/highlight": { 169 | "version": "0.16.0", 170 | "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz", 171 | "integrity": "sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==", 172 | "dependencies": { 173 | "@lezer/common": "^0.16.0" 174 | } 175 | }, 176 | "node_modules/@lezer/lr": { 177 | "version": "0.16.3", 178 | "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz", 179 | "integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==", 180 | "dependencies": { 181 | "@lezer/common": "^0.16.0" 182 | } 183 | }, 184 | "node_modules/@lezer/rust": { 185 | "version": "0.16.1", 186 | "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-0.16.1.tgz", 187 | "integrity": "sha512-9GuYKKAu+R4CpFWp7srF5gRA0ozuBbsP58h2ii/moWroVfR/5ABHvgQnByg3IMzopUvOIp8bUQzgn9xGho1ZDw==", 188 | "dependencies": { 189 | "@lezer/highlight": "^0.16.0", 190 | "@lezer/lr": "^0.16.0" 191 | } 192 | }, 193 | "node_modules/@nodelib/fs.scandir": { 194 | "version": "2.1.5", 195 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 196 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 197 | "dev": true, 198 | "dependencies": { 199 | "@nodelib/fs.stat": "2.0.5", 200 | "run-parallel": "^1.1.9" 201 | }, 202 | "engines": { 203 | "node": ">= 8" 204 | } 205 | }, 206 | "node_modules/@nodelib/fs.stat": { 207 | "version": "2.0.5", 208 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 209 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 210 | "dev": true, 211 | "engines": { 212 | "node": ">= 8" 213 | } 214 | }, 215 | "node_modules/@nodelib/fs.walk": { 216 | "version": "1.2.8", 217 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 218 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 219 | "dev": true, 220 | "dependencies": { 221 | "@nodelib/fs.scandir": "2.1.5", 222 | "fastq": "^1.6.0" 223 | }, 224 | "engines": { 225 | "node": ">= 8" 226 | } 227 | }, 228 | "node_modules/@rollup/pluginutils": { 229 | "version": "4.2.1", 230 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", 231 | "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", 232 | "dev": true, 233 | "dependencies": { 234 | "estree-walker": "^2.0.1", 235 | "picomatch": "^2.2.2" 236 | }, 237 | "engines": { 238 | "node": ">= 8.0.0" 239 | } 240 | }, 241 | "node_modules/@sveltejs/vite-plugin-svelte": { 242 | "version": "1.0.0-next.44", 243 | "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.44.tgz", 244 | "integrity": "sha512-n+sssEWbzykPS447FmnNyU5GxEhrBPDVd0lxNZnxRGz9P6651LjjwAnISKr3CKgT9v8IybP8VD0n2i5XzbqExg==", 245 | "dev": true, 246 | "dependencies": { 247 | "@rollup/pluginutils": "^4.2.1", 248 | "debug": "^4.3.4", 249 | "deepmerge": "^4.2.2", 250 | "kleur": "^4.1.4", 251 | "magic-string": "^0.26.1", 252 | "svelte-hmr": "^0.14.11" 253 | }, 254 | "engines": { 255 | "node": "^14.13.1 || >= 16" 256 | }, 257 | "peerDependencies": { 258 | "diff-match-patch": "^1.0.5", 259 | "svelte": "^3.44.0", 260 | "vite": "^2.9.0" 261 | }, 262 | "peerDependenciesMeta": { 263 | "diff-match-patch": { 264 | "optional": true 265 | } 266 | } 267 | }, 268 | "node_modules/@tsconfig/svelte": { 269 | "version": "2.0.1", 270 | "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-2.0.1.tgz", 271 | "integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==", 272 | "dev": true 273 | }, 274 | "node_modules/@types/lz-string": { 275 | "version": "1.3.34", 276 | "resolved": "https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz", 277 | "integrity": "sha512-j6G1e8DULJx3ONf6NdR5JiR2ZY3K3PaaqiEuKYkLQO0Czfi1AzrtjfnfCROyWGeDd5IVMKCwsgSmMip9OWijow==" 278 | }, 279 | "node_modules/@types/node": { 280 | "version": "17.0.33", 281 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.33.tgz", 282 | "integrity": "sha512-miWq2m2FiQZmaHfdZNcbpp9PuXg34W5JZ5CrJ/BaS70VuhoJENBEQybeiYSaPBRNq6KQGnjfEnc/F3PN++D+XQ==", 283 | "dev": true 284 | }, 285 | "node_modules/@types/pug": { 286 | "version": "2.0.6", 287 | "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", 288 | "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", 289 | "dev": true 290 | }, 291 | "node_modules/@types/sass": { 292 | "version": "1.43.1", 293 | "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", 294 | "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", 295 | "dev": true, 296 | "dependencies": { 297 | "@types/node": "*" 298 | } 299 | }, 300 | "node_modules/@zerodevx/svelte-toast": { 301 | "version": "0.7.2", 302 | "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.7.2.tgz", 303 | "integrity": "sha512-vWiY6IqsstcOoQ8PFBuFuxgPkj1JFAGhUF9gC7wLx7c5A9SSfdtxWs/39ekGSIeyJK0yqWhTcmzGrCEWSELzDw==" 304 | }, 305 | "node_modules/anymatch": { 306 | "version": "3.1.2", 307 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 308 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 309 | "dev": true, 310 | "dependencies": { 311 | "normalize-path": "^3.0.0", 312 | "picomatch": "^2.0.4" 313 | }, 314 | "engines": { 315 | "node": ">= 8" 316 | } 317 | }, 318 | "node_modules/balanced-match": { 319 | "version": "1.0.2", 320 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 321 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 322 | "dev": true 323 | }, 324 | "node_modules/binary-extensions": { 325 | "version": "2.2.0", 326 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 327 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 328 | "dev": true, 329 | "engines": { 330 | "node": ">=8" 331 | } 332 | }, 333 | "node_modules/brace-expansion": { 334 | "version": "1.1.11", 335 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 336 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 337 | "dev": true, 338 | "dependencies": { 339 | "balanced-match": "^1.0.0", 340 | "concat-map": "0.0.1" 341 | } 342 | }, 343 | "node_modules/braces": { 344 | "version": "3.0.2", 345 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 346 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 347 | "dev": true, 348 | "dependencies": { 349 | "fill-range": "^7.0.1" 350 | }, 351 | "engines": { 352 | "node": ">=8" 353 | } 354 | }, 355 | "node_modules/buffer-crc32": { 356 | "version": "0.2.13", 357 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 358 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 359 | "dev": true, 360 | "engines": { 361 | "node": "*" 362 | } 363 | }, 364 | "node_modules/callsites": { 365 | "version": "3.1.0", 366 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 367 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 368 | "dev": true, 369 | "engines": { 370 | "node": ">=6" 371 | } 372 | }, 373 | "node_modules/chokidar": { 374 | "version": "3.5.3", 375 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 376 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 377 | "dev": true, 378 | "funding": [ 379 | { 380 | "type": "individual", 381 | "url": "https://paulmillr.com/funding/" 382 | } 383 | ], 384 | "dependencies": { 385 | "anymatch": "~3.1.2", 386 | "braces": "~3.0.2", 387 | "glob-parent": "~5.1.2", 388 | "is-binary-path": "~2.1.0", 389 | "is-glob": "~4.0.1", 390 | "normalize-path": "~3.0.0", 391 | "readdirp": "~3.6.0" 392 | }, 393 | "engines": { 394 | "node": ">= 8.10.0" 395 | }, 396 | "optionalDependencies": { 397 | "fsevents": "~2.3.2" 398 | } 399 | }, 400 | "node_modules/concat-map": { 401 | "version": "0.0.1", 402 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 403 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 404 | "dev": true 405 | }, 406 | "node_modules/crelt": { 407 | "version": "1.0.5", 408 | "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", 409 | "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" 410 | }, 411 | "node_modules/debug": { 412 | "version": "4.3.4", 413 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 414 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 415 | "dev": true, 416 | "dependencies": { 417 | "ms": "2.1.2" 418 | }, 419 | "engines": { 420 | "node": ">=6.0" 421 | }, 422 | "peerDependenciesMeta": { 423 | "supports-color": { 424 | "optional": true 425 | } 426 | } 427 | }, 428 | "node_modules/deepmerge": { 429 | "version": "4.2.2", 430 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 431 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", 432 | "dev": true, 433 | "engines": { 434 | "node": ">=0.10.0" 435 | } 436 | }, 437 | "node_modules/detect-indent": { 438 | "version": "6.1.0", 439 | "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", 440 | "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", 441 | "dev": true, 442 | "engines": { 443 | "node": ">=8" 444 | } 445 | }, 446 | "node_modules/es6-promise": { 447 | "version": "3.3.1", 448 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", 449 | "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", 450 | "dev": true 451 | }, 452 | "node_modules/esbuild": { 453 | "version": "0.14.39", 454 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", 455 | "integrity": "sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ==", 456 | "dev": true, 457 | "hasInstallScript": true, 458 | "bin": { 459 | "esbuild": "bin/esbuild" 460 | }, 461 | "engines": { 462 | "node": ">=12" 463 | }, 464 | "optionalDependencies": { 465 | "esbuild-android-64": "0.14.39", 466 | "esbuild-android-arm64": "0.14.39", 467 | "esbuild-darwin-64": "0.14.39", 468 | "esbuild-darwin-arm64": "0.14.39", 469 | "esbuild-freebsd-64": "0.14.39", 470 | "esbuild-freebsd-arm64": "0.14.39", 471 | "esbuild-linux-32": "0.14.39", 472 | "esbuild-linux-64": "0.14.39", 473 | "esbuild-linux-arm": "0.14.39", 474 | "esbuild-linux-arm64": "0.14.39", 475 | "esbuild-linux-mips64le": "0.14.39", 476 | "esbuild-linux-ppc64le": "0.14.39", 477 | "esbuild-linux-riscv64": "0.14.39", 478 | "esbuild-linux-s390x": "0.14.39", 479 | "esbuild-netbsd-64": "0.14.39", 480 | "esbuild-openbsd-64": "0.14.39", 481 | "esbuild-sunos-64": "0.14.39", 482 | "esbuild-windows-32": "0.14.39", 483 | "esbuild-windows-64": "0.14.39", 484 | "esbuild-windows-arm64": "0.14.39" 485 | } 486 | }, 487 | "node_modules/esbuild-android-64": { 488 | "version": "0.14.39", 489 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", 490 | "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", 491 | "cpu": [ 492 | "x64" 493 | ], 494 | "dev": true, 495 | "optional": true, 496 | "os": [ 497 | "android" 498 | ], 499 | "engines": { 500 | "node": ">=12" 501 | } 502 | }, 503 | "node_modules/esbuild-android-arm64": { 504 | "version": "0.14.39", 505 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", 506 | "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", 507 | "cpu": [ 508 | "arm64" 509 | ], 510 | "dev": true, 511 | "optional": true, 512 | "os": [ 513 | "android" 514 | ], 515 | "engines": { 516 | "node": ">=12" 517 | } 518 | }, 519 | "node_modules/esbuild-darwin-64": { 520 | "version": "0.14.39", 521 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", 522 | "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", 523 | "cpu": [ 524 | "x64" 525 | ], 526 | "dev": true, 527 | "optional": true, 528 | "os": [ 529 | "darwin" 530 | ], 531 | "engines": { 532 | "node": ">=12" 533 | } 534 | }, 535 | "node_modules/esbuild-darwin-arm64": { 536 | "version": "0.14.39", 537 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", 538 | "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", 539 | "cpu": [ 540 | "arm64" 541 | ], 542 | "dev": true, 543 | "optional": true, 544 | "os": [ 545 | "darwin" 546 | ], 547 | "engines": { 548 | "node": ">=12" 549 | } 550 | }, 551 | "node_modules/esbuild-freebsd-64": { 552 | "version": "0.14.39", 553 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", 554 | "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", 555 | "cpu": [ 556 | "x64" 557 | ], 558 | "dev": true, 559 | "optional": true, 560 | "os": [ 561 | "freebsd" 562 | ], 563 | "engines": { 564 | "node": ">=12" 565 | } 566 | }, 567 | "node_modules/esbuild-freebsd-arm64": { 568 | "version": "0.14.39", 569 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", 570 | "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", 571 | "cpu": [ 572 | "arm64" 573 | ], 574 | "dev": true, 575 | "optional": true, 576 | "os": [ 577 | "freebsd" 578 | ], 579 | "engines": { 580 | "node": ">=12" 581 | } 582 | }, 583 | "node_modules/esbuild-linux-32": { 584 | "version": "0.14.39", 585 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", 586 | "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", 587 | "cpu": [ 588 | "ia32" 589 | ], 590 | "dev": true, 591 | "optional": true, 592 | "os": [ 593 | "linux" 594 | ], 595 | "engines": { 596 | "node": ">=12" 597 | } 598 | }, 599 | "node_modules/esbuild-linux-64": { 600 | "version": "0.14.39", 601 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", 602 | "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", 603 | "cpu": [ 604 | "x64" 605 | ], 606 | "dev": true, 607 | "optional": true, 608 | "os": [ 609 | "linux" 610 | ], 611 | "engines": { 612 | "node": ">=12" 613 | } 614 | }, 615 | "node_modules/esbuild-linux-arm": { 616 | "version": "0.14.39", 617 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", 618 | "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", 619 | "cpu": [ 620 | "arm" 621 | ], 622 | "dev": true, 623 | "optional": true, 624 | "os": [ 625 | "linux" 626 | ], 627 | "engines": { 628 | "node": ">=12" 629 | } 630 | }, 631 | "node_modules/esbuild-linux-arm64": { 632 | "version": "0.14.39", 633 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", 634 | "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", 635 | "cpu": [ 636 | "arm64" 637 | ], 638 | "dev": true, 639 | "optional": true, 640 | "os": [ 641 | "linux" 642 | ], 643 | "engines": { 644 | "node": ">=12" 645 | } 646 | }, 647 | "node_modules/esbuild-linux-mips64le": { 648 | "version": "0.14.39", 649 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", 650 | "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", 651 | "cpu": [ 652 | "mips64el" 653 | ], 654 | "dev": true, 655 | "optional": true, 656 | "os": [ 657 | "linux" 658 | ], 659 | "engines": { 660 | "node": ">=12" 661 | } 662 | }, 663 | "node_modules/esbuild-linux-ppc64le": { 664 | "version": "0.14.39", 665 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", 666 | "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", 667 | "cpu": [ 668 | "ppc64" 669 | ], 670 | "dev": true, 671 | "optional": true, 672 | "os": [ 673 | "linux" 674 | ], 675 | "engines": { 676 | "node": ">=12" 677 | } 678 | }, 679 | "node_modules/esbuild-linux-riscv64": { 680 | "version": "0.14.39", 681 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", 682 | "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", 683 | "cpu": [ 684 | "riscv64" 685 | ], 686 | "dev": true, 687 | "optional": true, 688 | "os": [ 689 | "linux" 690 | ], 691 | "engines": { 692 | "node": ">=12" 693 | } 694 | }, 695 | "node_modules/esbuild-linux-s390x": { 696 | "version": "0.14.39", 697 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", 698 | "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", 699 | "cpu": [ 700 | "s390x" 701 | ], 702 | "dev": true, 703 | "optional": true, 704 | "os": [ 705 | "linux" 706 | ], 707 | "engines": { 708 | "node": ">=12" 709 | } 710 | }, 711 | "node_modules/esbuild-netbsd-64": { 712 | "version": "0.14.39", 713 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", 714 | "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", 715 | "cpu": [ 716 | "x64" 717 | ], 718 | "dev": true, 719 | "optional": true, 720 | "os": [ 721 | "netbsd" 722 | ], 723 | "engines": { 724 | "node": ">=12" 725 | } 726 | }, 727 | "node_modules/esbuild-openbsd-64": { 728 | "version": "0.14.39", 729 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", 730 | "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", 731 | "cpu": [ 732 | "x64" 733 | ], 734 | "dev": true, 735 | "optional": true, 736 | "os": [ 737 | "openbsd" 738 | ], 739 | "engines": { 740 | "node": ">=12" 741 | } 742 | }, 743 | "node_modules/esbuild-sunos-64": { 744 | "version": "0.14.39", 745 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", 746 | "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", 747 | "cpu": [ 748 | "x64" 749 | ], 750 | "dev": true, 751 | "optional": true, 752 | "os": [ 753 | "sunos" 754 | ], 755 | "engines": { 756 | "node": ">=12" 757 | } 758 | }, 759 | "node_modules/esbuild-windows-32": { 760 | "version": "0.14.39", 761 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", 762 | "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", 763 | "cpu": [ 764 | "ia32" 765 | ], 766 | "dev": true, 767 | "optional": true, 768 | "os": [ 769 | "win32" 770 | ], 771 | "engines": { 772 | "node": ">=12" 773 | } 774 | }, 775 | "node_modules/esbuild-windows-64": { 776 | "version": "0.14.39", 777 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", 778 | "integrity": "sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow==", 779 | "cpu": [ 780 | "x64" 781 | ], 782 | "dev": true, 783 | "optional": true, 784 | "os": [ 785 | "win32" 786 | ], 787 | "engines": { 788 | "node": ">=12" 789 | } 790 | }, 791 | "node_modules/esbuild-windows-arm64": { 792 | "version": "0.14.39", 793 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", 794 | "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", 795 | "cpu": [ 796 | "arm64" 797 | ], 798 | "dev": true, 799 | "optional": true, 800 | "os": [ 801 | "win32" 802 | ], 803 | "engines": { 804 | "node": ">=12" 805 | } 806 | }, 807 | "node_modules/estree-walker": { 808 | "version": "2.0.2", 809 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 810 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 811 | "dev": true 812 | }, 813 | "node_modules/fast-glob": { 814 | "version": "3.2.11", 815 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", 816 | "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", 817 | "dev": true, 818 | "dependencies": { 819 | "@nodelib/fs.stat": "^2.0.2", 820 | "@nodelib/fs.walk": "^1.2.3", 821 | "glob-parent": "^5.1.2", 822 | "merge2": "^1.3.0", 823 | "micromatch": "^4.0.4" 824 | }, 825 | "engines": { 826 | "node": ">=8.6.0" 827 | } 828 | }, 829 | "node_modules/fastq": { 830 | "version": "1.13.0", 831 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", 832 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", 833 | "dev": true, 834 | "dependencies": { 835 | "reusify": "^1.0.4" 836 | } 837 | }, 838 | "node_modules/fill-range": { 839 | "version": "7.0.1", 840 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 841 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 842 | "dev": true, 843 | "dependencies": { 844 | "to-regex-range": "^5.0.1" 845 | }, 846 | "engines": { 847 | "node": ">=8" 848 | } 849 | }, 850 | "node_modules/formatter": { 851 | "resolved": "../formatter/pkg", 852 | "link": true 853 | }, 854 | "node_modules/fs.realpath": { 855 | "version": "1.0.0", 856 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 857 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 858 | "dev": true 859 | }, 860 | "node_modules/fsevents": { 861 | "version": "2.3.2", 862 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 863 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 864 | "dev": true, 865 | "hasInstallScript": true, 866 | "optional": true, 867 | "os": [ 868 | "darwin" 869 | ], 870 | "engines": { 871 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 872 | } 873 | }, 874 | "node_modules/function-bind": { 875 | "version": "1.1.1", 876 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 877 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 878 | "dev": true 879 | }, 880 | "node_modules/glob": { 881 | "version": "7.2.2", 882 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.2.tgz", 883 | "integrity": "sha512-NzDgHDiJwKYByLrL5lONmQFpK/2G78SMMfo+E9CuGlX4IkvfKDsiQSNPwAYxEy+e6p7ZQ3uslSLlwlJcqezBmQ==", 884 | "dev": true, 885 | "dependencies": { 886 | "fs.realpath": "^1.0.0", 887 | "inflight": "^1.0.4", 888 | "inherits": "2", 889 | "minimatch": "^3.1.1", 890 | "once": "^1.3.0", 891 | "path-is-absolute": "^1.0.0" 892 | }, 893 | "engines": { 894 | "node": "*" 895 | }, 896 | "funding": { 897 | "url": "https://github.com/sponsors/isaacs" 898 | } 899 | }, 900 | "node_modules/glob-parent": { 901 | "version": "5.1.2", 902 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 903 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 904 | "dev": true, 905 | "dependencies": { 906 | "is-glob": "^4.0.1" 907 | }, 908 | "engines": { 909 | "node": ">= 6" 910 | } 911 | }, 912 | "node_modules/graceful-fs": { 913 | "version": "4.2.10", 914 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 915 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", 916 | "dev": true 917 | }, 918 | "node_modules/has": { 919 | "version": "1.0.3", 920 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 921 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 922 | "dev": true, 923 | "dependencies": { 924 | "function-bind": "^1.1.1" 925 | }, 926 | "engines": { 927 | "node": ">= 0.4.0" 928 | } 929 | }, 930 | "node_modules/import-fresh": { 931 | "version": "3.3.0", 932 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 933 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 934 | "dev": true, 935 | "dependencies": { 936 | "parent-module": "^1.0.0", 937 | "resolve-from": "^4.0.0" 938 | }, 939 | "engines": { 940 | "node": ">=6" 941 | }, 942 | "funding": { 943 | "url": "https://github.com/sponsors/sindresorhus" 944 | } 945 | }, 946 | "node_modules/inflight": { 947 | "version": "1.0.6", 948 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 949 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 950 | "dev": true, 951 | "dependencies": { 952 | "once": "^1.3.0", 953 | "wrappy": "1" 954 | } 955 | }, 956 | "node_modules/inherits": { 957 | "version": "2.0.4", 958 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 959 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 960 | "dev": true 961 | }, 962 | "node_modules/is-binary-path": { 963 | "version": "2.1.0", 964 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 965 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 966 | "dev": true, 967 | "dependencies": { 968 | "binary-extensions": "^2.0.0" 969 | }, 970 | "engines": { 971 | "node": ">=8" 972 | } 973 | }, 974 | "node_modules/is-core-module": { 975 | "version": "2.9.0", 976 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", 977 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", 978 | "dev": true, 979 | "dependencies": { 980 | "has": "^1.0.3" 981 | }, 982 | "funding": { 983 | "url": "https://github.com/sponsors/ljharb" 984 | } 985 | }, 986 | "node_modules/is-extglob": { 987 | "version": "2.1.1", 988 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 989 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 990 | "dev": true, 991 | "engines": { 992 | "node": ">=0.10.0" 993 | } 994 | }, 995 | "node_modules/is-glob": { 996 | "version": "4.0.3", 997 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 998 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 999 | "dev": true, 1000 | "dependencies": { 1001 | "is-extglob": "^2.1.1" 1002 | }, 1003 | "engines": { 1004 | "node": ">=0.10.0" 1005 | } 1006 | }, 1007 | "node_modules/is-number": { 1008 | "version": "7.0.0", 1009 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1010 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1011 | "dev": true, 1012 | "engines": { 1013 | "node": ">=0.12.0" 1014 | } 1015 | }, 1016 | "node_modules/kleur": { 1017 | "version": "4.1.4", 1018 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", 1019 | "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", 1020 | "dev": true, 1021 | "engines": { 1022 | "node": ">=6" 1023 | } 1024 | }, 1025 | "node_modules/lz-string": { 1026 | "version": "1.4.4", 1027 | "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", 1028 | "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=", 1029 | "bin": { 1030 | "lz-string": "bin/bin.js" 1031 | } 1032 | }, 1033 | "node_modules/magic-string": { 1034 | "version": "0.26.2", 1035 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz", 1036 | "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==", 1037 | "dev": true, 1038 | "dependencies": { 1039 | "sourcemap-codec": "^1.4.8" 1040 | }, 1041 | "engines": { 1042 | "node": ">=12" 1043 | } 1044 | }, 1045 | "node_modules/merge2": { 1046 | "version": "1.4.1", 1047 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1048 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1049 | "dev": true, 1050 | "engines": { 1051 | "node": ">= 8" 1052 | } 1053 | }, 1054 | "node_modules/micromatch": { 1055 | "version": "4.0.5", 1056 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", 1057 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 1058 | "dev": true, 1059 | "dependencies": { 1060 | "braces": "^3.0.2", 1061 | "picomatch": "^2.3.1" 1062 | }, 1063 | "engines": { 1064 | "node": ">=8.6" 1065 | } 1066 | }, 1067 | "node_modules/min-indent": { 1068 | "version": "1.0.1", 1069 | "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", 1070 | "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", 1071 | "dev": true, 1072 | "engines": { 1073 | "node": ">=4" 1074 | } 1075 | }, 1076 | "node_modules/minimatch": { 1077 | "version": "3.1.2", 1078 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1079 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1080 | "dev": true, 1081 | "dependencies": { 1082 | "brace-expansion": "^1.1.7" 1083 | }, 1084 | "engines": { 1085 | "node": "*" 1086 | } 1087 | }, 1088 | "node_modules/minimist": { 1089 | "version": "1.2.6", 1090 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 1091 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", 1092 | "dev": true 1093 | }, 1094 | "node_modules/mkdirp": { 1095 | "version": "0.5.6", 1096 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 1097 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 1098 | "dev": true, 1099 | "dependencies": { 1100 | "minimist": "^1.2.6" 1101 | }, 1102 | "bin": { 1103 | "mkdirp": "bin/cmd.js" 1104 | } 1105 | }, 1106 | "node_modules/mri": { 1107 | "version": "1.2.0", 1108 | "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", 1109 | "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", 1110 | "dev": true, 1111 | "engines": { 1112 | "node": ">=4" 1113 | } 1114 | }, 1115 | "node_modules/ms": { 1116 | "version": "2.1.2", 1117 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1118 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1119 | "dev": true 1120 | }, 1121 | "node_modules/nanoid": { 1122 | "version": "3.3.4", 1123 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 1124 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 1125 | "dev": true, 1126 | "bin": { 1127 | "nanoid": "bin/nanoid.cjs" 1128 | }, 1129 | "engines": { 1130 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1131 | } 1132 | }, 1133 | "node_modules/normalize-path": { 1134 | "version": "3.0.0", 1135 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1136 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1137 | "dev": true, 1138 | "engines": { 1139 | "node": ">=0.10.0" 1140 | } 1141 | }, 1142 | "node_modules/once": { 1143 | "version": "1.4.0", 1144 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1145 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1146 | "dev": true, 1147 | "dependencies": { 1148 | "wrappy": "1" 1149 | } 1150 | }, 1151 | "node_modules/parent-module": { 1152 | "version": "1.0.1", 1153 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1154 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1155 | "dev": true, 1156 | "dependencies": { 1157 | "callsites": "^3.0.0" 1158 | }, 1159 | "engines": { 1160 | "node": ">=6" 1161 | } 1162 | }, 1163 | "node_modules/path-is-absolute": { 1164 | "version": "1.0.1", 1165 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1166 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1167 | "dev": true, 1168 | "engines": { 1169 | "node": ">=0.10.0" 1170 | } 1171 | }, 1172 | "node_modules/path-parse": { 1173 | "version": "1.0.7", 1174 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1175 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1176 | "dev": true 1177 | }, 1178 | "node_modules/picocolors": { 1179 | "version": "1.0.0", 1180 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1181 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1182 | "dev": true 1183 | }, 1184 | "node_modules/picomatch": { 1185 | "version": "2.3.1", 1186 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1187 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1188 | "dev": true, 1189 | "engines": { 1190 | "node": ">=8.6" 1191 | }, 1192 | "funding": { 1193 | "url": "https://github.com/sponsors/jonschlinkert" 1194 | } 1195 | }, 1196 | "node_modules/postcss": { 1197 | "version": "8.4.13", 1198 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", 1199 | "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", 1200 | "dev": true, 1201 | "funding": [ 1202 | { 1203 | "type": "opencollective", 1204 | "url": "https://opencollective.com/postcss/" 1205 | }, 1206 | { 1207 | "type": "tidelift", 1208 | "url": "https://tidelift.com/funding/github/npm/postcss" 1209 | } 1210 | ], 1211 | "dependencies": { 1212 | "nanoid": "^3.3.3", 1213 | "picocolors": "^1.0.0", 1214 | "source-map-js": "^1.0.2" 1215 | }, 1216 | "engines": { 1217 | "node": "^10 || ^12 || >=14" 1218 | } 1219 | }, 1220 | "node_modules/queue-microtask": { 1221 | "version": "1.2.3", 1222 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1223 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1224 | "dev": true, 1225 | "funding": [ 1226 | { 1227 | "type": "github", 1228 | "url": "https://github.com/sponsors/feross" 1229 | }, 1230 | { 1231 | "type": "patreon", 1232 | "url": "https://www.patreon.com/feross" 1233 | }, 1234 | { 1235 | "type": "consulting", 1236 | "url": "https://feross.org/support" 1237 | } 1238 | ] 1239 | }, 1240 | "node_modules/readdirp": { 1241 | "version": "3.6.0", 1242 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1243 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1244 | "dev": true, 1245 | "dependencies": { 1246 | "picomatch": "^2.2.1" 1247 | }, 1248 | "engines": { 1249 | "node": ">=8.10.0" 1250 | } 1251 | }, 1252 | "node_modules/resolve": { 1253 | "version": "1.22.0", 1254 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", 1255 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", 1256 | "dev": true, 1257 | "dependencies": { 1258 | "is-core-module": "^2.8.1", 1259 | "path-parse": "^1.0.7", 1260 | "supports-preserve-symlinks-flag": "^1.0.0" 1261 | }, 1262 | "bin": { 1263 | "resolve": "bin/resolve" 1264 | }, 1265 | "funding": { 1266 | "url": "https://github.com/sponsors/ljharb" 1267 | } 1268 | }, 1269 | "node_modules/resolve-from": { 1270 | "version": "4.0.0", 1271 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1272 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1273 | "dev": true, 1274 | "engines": { 1275 | "node": ">=4" 1276 | } 1277 | }, 1278 | "node_modules/reusify": { 1279 | "version": "1.0.4", 1280 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1281 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1282 | "dev": true, 1283 | "engines": { 1284 | "iojs": ">=1.0.0", 1285 | "node": ">=0.10.0" 1286 | } 1287 | }, 1288 | "node_modules/rimraf": { 1289 | "version": "2.7.1", 1290 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 1291 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 1292 | "dev": true, 1293 | "dependencies": { 1294 | "glob": "^7.1.3" 1295 | }, 1296 | "bin": { 1297 | "rimraf": "bin.js" 1298 | } 1299 | }, 1300 | "node_modules/rollup": { 1301 | "version": "2.73.0", 1302 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.73.0.tgz", 1303 | "integrity": "sha512-h/UngC3S4Zt28mB3g0+2YCMegT5yoftnQplwzPqGZcKvlld5e+kT/QRmJiL+qxGyZKOYpgirWGdLyEO1b0dpLQ==", 1304 | "dev": true, 1305 | "bin": { 1306 | "rollup": "dist/bin/rollup" 1307 | }, 1308 | "engines": { 1309 | "node": ">=10.0.0" 1310 | }, 1311 | "optionalDependencies": { 1312 | "fsevents": "~2.3.2" 1313 | } 1314 | }, 1315 | "node_modules/run-parallel": { 1316 | "version": "1.2.0", 1317 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1318 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1319 | "dev": true, 1320 | "funding": [ 1321 | { 1322 | "type": "github", 1323 | "url": "https://github.com/sponsors/feross" 1324 | }, 1325 | { 1326 | "type": "patreon", 1327 | "url": "https://www.patreon.com/feross" 1328 | }, 1329 | { 1330 | "type": "consulting", 1331 | "url": "https://feross.org/support" 1332 | } 1333 | ], 1334 | "dependencies": { 1335 | "queue-microtask": "^1.2.2" 1336 | } 1337 | }, 1338 | "node_modules/sade": { 1339 | "version": "1.8.1", 1340 | "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", 1341 | "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", 1342 | "dev": true, 1343 | "dependencies": { 1344 | "mri": "^1.1.0" 1345 | }, 1346 | "engines": { 1347 | "node": ">=6" 1348 | } 1349 | }, 1350 | "node_modules/sander": { 1351 | "version": "0.5.1", 1352 | "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", 1353 | "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=", 1354 | "dev": true, 1355 | "dependencies": { 1356 | "es6-promise": "^3.1.2", 1357 | "graceful-fs": "^4.1.3", 1358 | "mkdirp": "^0.5.1", 1359 | "rimraf": "^2.5.2" 1360 | } 1361 | }, 1362 | "node_modules/sorcery": { 1363 | "version": "0.10.0", 1364 | "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", 1365 | "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=", 1366 | "dev": true, 1367 | "dependencies": { 1368 | "buffer-crc32": "^0.2.5", 1369 | "minimist": "^1.2.0", 1370 | "sander": "^0.5.0", 1371 | "sourcemap-codec": "^1.3.0" 1372 | }, 1373 | "bin": { 1374 | "sorcery": "bin/index.js" 1375 | } 1376 | }, 1377 | "node_modules/source-map-js": { 1378 | "version": "1.0.2", 1379 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1380 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1381 | "dev": true, 1382 | "engines": { 1383 | "node": ">=0.10.0" 1384 | } 1385 | }, 1386 | "node_modules/sourcemap-codec": { 1387 | "version": "1.4.8", 1388 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 1389 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 1390 | "dev": true 1391 | }, 1392 | "node_modules/strip-indent": { 1393 | "version": "3.0.0", 1394 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", 1395 | "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", 1396 | "dev": true, 1397 | "dependencies": { 1398 | "min-indent": "^1.0.0" 1399 | }, 1400 | "engines": { 1401 | "node": ">=8" 1402 | } 1403 | }, 1404 | "node_modules/style-mod": { 1405 | "version": "4.0.0", 1406 | "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", 1407 | "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==" 1408 | }, 1409 | "node_modules/supports-preserve-symlinks-flag": { 1410 | "version": "1.0.0", 1411 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1412 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 1413 | "dev": true, 1414 | "engines": { 1415 | "node": ">= 0.4" 1416 | }, 1417 | "funding": { 1418 | "url": "https://github.com/sponsors/ljharb" 1419 | } 1420 | }, 1421 | "node_modules/svelte": { 1422 | "version": "3.48.0", 1423 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.48.0.tgz", 1424 | "integrity": "sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==", 1425 | "dev": true, 1426 | "engines": { 1427 | "node": ">= 8" 1428 | } 1429 | }, 1430 | "node_modules/svelte-check": { 1431 | "version": "2.7.1", 1432 | "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.7.1.tgz", 1433 | "integrity": "sha512-vHVu2+SQ6ibt77iTQaq2oiOjBgGL48qqcg0ZdEOsP5pPOjgeyR9QbnaEdzdBs9nsVYBc/42haKtzb2uFqS8GVw==", 1434 | "dev": true, 1435 | "dependencies": { 1436 | "@jridgewell/trace-mapping": "^0.3.9", 1437 | "chokidar": "^3.4.1", 1438 | "fast-glob": "^3.2.7", 1439 | "import-fresh": "^3.2.1", 1440 | "picocolors": "^1.0.0", 1441 | "sade": "^1.7.4", 1442 | "svelte-preprocess": "^4.0.0", 1443 | "typescript": "*" 1444 | }, 1445 | "bin": { 1446 | "svelte-check": "bin/svelte-check" 1447 | }, 1448 | "peerDependencies": { 1449 | "svelte": "^3.24.0" 1450 | } 1451 | }, 1452 | "node_modules/svelte-hmr": { 1453 | "version": "0.14.11", 1454 | "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.11.tgz", 1455 | "integrity": "sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==", 1456 | "dev": true, 1457 | "engines": { 1458 | "node": "^12.20 || ^14.13.1 || >= 16" 1459 | }, 1460 | "peerDependencies": { 1461 | "svelte": ">=3.19.0" 1462 | } 1463 | }, 1464 | "node_modules/svelte-loading-spinners": { 1465 | "version": "0.1.7", 1466 | "resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.1.7.tgz", 1467 | "integrity": "sha512-EKCId1DjVL2RSUVJJsvtNcqQHox03XIgh4xh/4p7r6ST7d8mut6INY9/LqK4A17PFU64+3quZmqiSfOlf480CA==" 1468 | }, 1469 | "node_modules/svelte-preprocess": { 1470 | "version": "4.10.6", 1471 | "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.6.tgz", 1472 | "integrity": "sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ==", 1473 | "dev": true, 1474 | "hasInstallScript": true, 1475 | "dependencies": { 1476 | "@types/pug": "^2.0.4", 1477 | "@types/sass": "^1.16.0", 1478 | "detect-indent": "^6.0.0", 1479 | "magic-string": "^0.25.7", 1480 | "sorcery": "^0.10.0", 1481 | "strip-indent": "^3.0.0" 1482 | }, 1483 | "engines": { 1484 | "node": ">= 9.11.2" 1485 | }, 1486 | "peerDependencies": { 1487 | "@babel/core": "^7.10.2", 1488 | "coffeescript": "^2.5.1", 1489 | "less": "^3.11.3 || ^4.0.0", 1490 | "postcss": "^7 || ^8", 1491 | "postcss-load-config": "^2.1.0 || ^3.0.0", 1492 | "pug": "^3.0.0", 1493 | "sass": "^1.26.8", 1494 | "stylus": "^0.55.0", 1495 | "sugarss": "^2.0.0", 1496 | "svelte": "^3.23.0", 1497 | "typescript": "^3.9.5 || ^4.0.0" 1498 | }, 1499 | "peerDependenciesMeta": { 1500 | "@babel/core": { 1501 | "optional": true 1502 | }, 1503 | "coffeescript": { 1504 | "optional": true 1505 | }, 1506 | "less": { 1507 | "optional": true 1508 | }, 1509 | "node-sass": { 1510 | "optional": true 1511 | }, 1512 | "postcss": { 1513 | "optional": true 1514 | }, 1515 | "postcss-load-config": { 1516 | "optional": true 1517 | }, 1518 | "pug": { 1519 | "optional": true 1520 | }, 1521 | "sass": { 1522 | "optional": true 1523 | }, 1524 | "stylus": { 1525 | "optional": true 1526 | }, 1527 | "sugarss": { 1528 | "optional": true 1529 | }, 1530 | "typescript": { 1531 | "optional": true 1532 | } 1533 | } 1534 | }, 1535 | "node_modules/svelte-preprocess/node_modules/magic-string": { 1536 | "version": "0.25.9", 1537 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", 1538 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", 1539 | "dev": true, 1540 | "dependencies": { 1541 | "sourcemap-codec": "^1.4.8" 1542 | } 1543 | }, 1544 | "node_modules/to-regex-range": { 1545 | "version": "5.0.1", 1546 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1547 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1548 | "dev": true, 1549 | "dependencies": { 1550 | "is-number": "^7.0.0" 1551 | }, 1552 | "engines": { 1553 | "node": ">=8.0" 1554 | } 1555 | }, 1556 | "node_modules/tslib": { 1557 | "version": "2.4.0", 1558 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", 1559 | "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", 1560 | "dev": true 1561 | }, 1562 | "node_modules/typescript": { 1563 | "version": "4.6.4", 1564 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", 1565 | "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", 1566 | "dev": true, 1567 | "bin": { 1568 | "tsc": "bin/tsc", 1569 | "tsserver": "bin/tsserver" 1570 | }, 1571 | "engines": { 1572 | "node": ">=4.2.0" 1573 | } 1574 | }, 1575 | "node_modules/vite": { 1576 | "version": "2.9.9", 1577 | "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", 1578 | "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", 1579 | "dev": true, 1580 | "dependencies": { 1581 | "esbuild": "^0.14.27", 1582 | "postcss": "^8.4.13", 1583 | "resolve": "^1.22.0", 1584 | "rollup": "^2.59.0" 1585 | }, 1586 | "bin": { 1587 | "vite": "bin/vite.js" 1588 | }, 1589 | "engines": { 1590 | "node": ">=12.2.0" 1591 | }, 1592 | "optionalDependencies": { 1593 | "fsevents": "~2.3.2" 1594 | }, 1595 | "peerDependencies": { 1596 | "less": "*", 1597 | "sass": "*", 1598 | "stylus": "*" 1599 | }, 1600 | "peerDependenciesMeta": { 1601 | "less": { 1602 | "optional": true 1603 | }, 1604 | "sass": { 1605 | "optional": true 1606 | }, 1607 | "stylus": { 1608 | "optional": true 1609 | } 1610 | } 1611 | }, 1612 | "node_modules/w3c-keyname": { 1613 | "version": "2.2.4", 1614 | "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", 1615 | "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" 1616 | }, 1617 | "node_modules/wrappy": { 1618 | "version": "1.0.2", 1619 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1620 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1621 | "dev": true 1622 | } 1623 | }, 1624 | "dependencies": { 1625 | "@codemirror/autocomplete": { 1626 | "version": "0.20.0", 1627 | "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.20.0.tgz", 1628 | "integrity": "sha512-F6VOM8lImn5ApqxJcaWgdl7hhlw8B5yAfZJGlsQifcpNotkZOMND61mBFZ84OmSLWxtT8/smkSeLvJupKbjP9w==", 1629 | "requires": { 1630 | "@codemirror/language": "^0.20.0", 1631 | "@codemirror/state": "^0.20.0", 1632 | "@codemirror/view": "^0.20.0", 1633 | "@lezer/common": "^0.16.0" 1634 | } 1635 | }, 1636 | "@codemirror/basic-setup": { 1637 | "version": "0.20.0", 1638 | "resolved": "https://registry.npmjs.org/@codemirror/basic-setup/-/basic-setup-0.20.0.tgz", 1639 | "integrity": "sha512-W/ERKMLErWkrVLyP5I8Yh8PXl4r+WFNkdYVSzkXYPQv2RMPSkWpr2BgggiSJ8AHF/q3GuApncDD8I4BZz65fyg==", 1640 | "requires": { 1641 | "@codemirror/autocomplete": "^0.20.0", 1642 | "@codemirror/commands": "^0.20.0", 1643 | "@codemirror/language": "^0.20.0", 1644 | "@codemirror/lint": "^0.20.0", 1645 | "@codemirror/search": "^0.20.0", 1646 | "@codemirror/state": "^0.20.0", 1647 | "@codemirror/view": "^0.20.0" 1648 | } 1649 | }, 1650 | "@codemirror/commands": { 1651 | "version": "0.20.0", 1652 | "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-0.20.0.tgz", 1653 | "integrity": "sha512-v9L5NNVA+A9R6zaFvaTbxs30kc69F6BkOoiEbeFw4m4I0exmDEKBILN6mK+GksJtvTzGBxvhAPlVFTdQW8GB7Q==", 1654 | "requires": { 1655 | "@codemirror/language": "^0.20.0", 1656 | "@codemirror/state": "^0.20.0", 1657 | "@codemirror/view": "^0.20.0", 1658 | "@lezer/common": "^0.16.0" 1659 | } 1660 | }, 1661 | "@codemirror/lang-rust": { 1662 | "version": "0.20.0", 1663 | "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-0.20.0.tgz", 1664 | "integrity": "sha512-H49ONe7TQSD6n9X7je56wEmsE5rPC7vgDxxAoWUEQGQWzIlrQD2gRrfqe4y+dbD/yGVhjWla7UyuyUPQVpGJyg==", 1665 | "requires": { 1666 | "@codemirror/language": "^0.20.0", 1667 | "@lezer/rust": "^0.16.0" 1668 | } 1669 | }, 1670 | "@codemirror/language": { 1671 | "version": "0.20.0", 1672 | "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.20.0.tgz", 1673 | "integrity": "sha512-lPsF5Y2ZFd5lZ9+7HXTxu57Po3dms3+7q2iAffzrbis2wyJo0lzi/j2312EKStEzwd0pGGpvrUk2dEd333N2jw==", 1674 | "requires": { 1675 | "@codemirror/state": "^0.20.0", 1676 | "@codemirror/view": "^0.20.0", 1677 | "@lezer/common": "^0.16.0", 1678 | "@lezer/highlight": "^0.16.0", 1679 | "@lezer/lr": "^0.16.0" 1680 | } 1681 | }, 1682 | "@codemirror/lint": { 1683 | "version": "0.20.2", 1684 | "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-0.20.2.tgz", 1685 | "integrity": "sha512-xEH3wlzoFLEhPEeMVRNoQIhoTCMEtXhVxemGh3FYjLfl/CL3B2Wz+CU7ooP5SKhN1le7JqUNSfiTArFP+IzFuw==", 1686 | "requires": { 1687 | "@codemirror/state": "^0.20.0", 1688 | "@codemirror/view": "^0.20.2", 1689 | "crelt": "^1.0.5" 1690 | } 1691 | }, 1692 | "@codemirror/search": { 1693 | "version": "0.20.1", 1694 | "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-0.20.1.tgz", 1695 | "integrity": "sha512-ROe6gRboQU5E4z6GAkNa2kxhXqsGNbeLEisbvzbOeB7nuDYXUZ70vGIgmqPu0tB+1M3F9yWk6W8k2vrFpJaD4Q==", 1696 | "requires": { 1697 | "@codemirror/state": "^0.20.0", 1698 | "@codemirror/view": "^0.20.0", 1699 | "crelt": "^1.0.5" 1700 | } 1701 | }, 1702 | "@codemirror/state": { 1703 | "version": "0.20.0", 1704 | "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.20.0.tgz", 1705 | "integrity": "sha512-R3XrAWCS5Xm9lx+4pDET4EUPEg+8bDfAa5zoOFIhx+VChsfew9Vy33dAjCXS5ES4Q8UecW4WM4UudmUFpZ+86A==" 1706 | }, 1707 | "@codemirror/theme-one-dark": { 1708 | "version": "0.20.0", 1709 | "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-0.20.0.tgz", 1710 | "integrity": "sha512-iqTKaiOZddwlc2rYF+9D60Gfyz9EsSawVejSjyP2FCtOwZ1X0frG5/ByTKH5FBDD2+P7W8+h/OIG4r5dWq4bgA==", 1711 | "requires": { 1712 | "@codemirror/language": "^0.20.0", 1713 | "@codemirror/state": "^0.20.0", 1714 | "@codemirror/view": "^0.20.0", 1715 | "@lezer/highlight": "^0.16.0" 1716 | } 1717 | }, 1718 | "@codemirror/view": { 1719 | "version": "0.20.4", 1720 | "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.20.4.tgz", 1721 | "integrity": "sha512-6yprcc0/39EzI6y9Jm/J5F9lFzQik0yj8gE3CO/wOCQ4vd3Drol114mMK91LGtKrfoS0MFKVGulw0TdfN49Bfw==", 1722 | "requires": { 1723 | "@codemirror/state": "^0.20.0", 1724 | "style-mod": "^4.0.0", 1725 | "w3c-keyname": "^2.2.4" 1726 | } 1727 | }, 1728 | "@jridgewell/resolve-uri": { 1729 | "version": "3.0.7", 1730 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", 1731 | "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", 1732 | "dev": true 1733 | }, 1734 | "@jridgewell/sourcemap-codec": { 1735 | "version": "1.4.13", 1736 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", 1737 | "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", 1738 | "dev": true 1739 | }, 1740 | "@jridgewell/trace-mapping": { 1741 | "version": "0.3.13", 1742 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", 1743 | "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", 1744 | "dev": true, 1745 | "requires": { 1746 | "@jridgewell/resolve-uri": "^3.0.3", 1747 | "@jridgewell/sourcemap-codec": "^1.4.10" 1748 | } 1749 | }, 1750 | "@lezer/common": { 1751 | "version": "0.16.0", 1752 | "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.16.0.tgz", 1753 | "integrity": "sha512-H6sPCku+asKWYaNjwfQ1Uvcay9UP1Pdzu4qpy8GtRZ0cKT2AAGnj9MQGiRtY18MDntvhYRJxNGv7FNWOSV/e8A==" 1754 | }, 1755 | "@lezer/highlight": { 1756 | "version": "0.16.0", 1757 | "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-0.16.0.tgz", 1758 | "integrity": "sha512-iE5f4flHlJ1g1clOStvXNLbORJoiW4Kytso6ubfYzHnaNo/eo5SKhxs4wv/rtvwZQeZrK3we8S9SyA7OGOoRKQ==", 1759 | "requires": { 1760 | "@lezer/common": "^0.16.0" 1761 | } 1762 | }, 1763 | "@lezer/lr": { 1764 | "version": "0.16.3", 1765 | "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.16.3.tgz", 1766 | "integrity": "sha512-pau7um4eAw94BEuuShUIeQDTf3k4Wt6oIUOYxMmkZgDHdqtIcxWND4LRxi8nI9KuT4I1bXQv67BCapkxt7Ywqw==", 1767 | "requires": { 1768 | "@lezer/common": "^0.16.0" 1769 | } 1770 | }, 1771 | "@lezer/rust": { 1772 | "version": "0.16.1", 1773 | "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-0.16.1.tgz", 1774 | "integrity": "sha512-9GuYKKAu+R4CpFWp7srF5gRA0ozuBbsP58h2ii/moWroVfR/5ABHvgQnByg3IMzopUvOIp8bUQzgn9xGho1ZDw==", 1775 | "requires": { 1776 | "@lezer/highlight": "^0.16.0", 1777 | "@lezer/lr": "^0.16.0" 1778 | } 1779 | }, 1780 | "@nodelib/fs.scandir": { 1781 | "version": "2.1.5", 1782 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 1783 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 1784 | "dev": true, 1785 | "requires": { 1786 | "@nodelib/fs.stat": "2.0.5", 1787 | "run-parallel": "^1.1.9" 1788 | } 1789 | }, 1790 | "@nodelib/fs.stat": { 1791 | "version": "2.0.5", 1792 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 1793 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 1794 | "dev": true 1795 | }, 1796 | "@nodelib/fs.walk": { 1797 | "version": "1.2.8", 1798 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 1799 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 1800 | "dev": true, 1801 | "requires": { 1802 | "@nodelib/fs.scandir": "2.1.5", 1803 | "fastq": "^1.6.0" 1804 | } 1805 | }, 1806 | "@rollup/pluginutils": { 1807 | "version": "4.2.1", 1808 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", 1809 | "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", 1810 | "dev": true, 1811 | "requires": { 1812 | "estree-walker": "^2.0.1", 1813 | "picomatch": "^2.2.2" 1814 | } 1815 | }, 1816 | "@sveltejs/vite-plugin-svelte": { 1817 | "version": "1.0.0-next.44", 1818 | "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.44.tgz", 1819 | "integrity": "sha512-n+sssEWbzykPS447FmnNyU5GxEhrBPDVd0lxNZnxRGz9P6651LjjwAnISKr3CKgT9v8IybP8VD0n2i5XzbqExg==", 1820 | "dev": true, 1821 | "requires": { 1822 | "@rollup/pluginutils": "^4.2.1", 1823 | "debug": "^4.3.4", 1824 | "deepmerge": "^4.2.2", 1825 | "kleur": "^4.1.4", 1826 | "magic-string": "^0.26.1", 1827 | "svelte-hmr": "^0.14.11" 1828 | } 1829 | }, 1830 | "@tsconfig/svelte": { 1831 | "version": "2.0.1", 1832 | "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-2.0.1.tgz", 1833 | "integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==", 1834 | "dev": true 1835 | }, 1836 | "@types/lz-string": { 1837 | "version": "1.3.34", 1838 | "resolved": "https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz", 1839 | "integrity": "sha512-j6G1e8DULJx3ONf6NdR5JiR2ZY3K3PaaqiEuKYkLQO0Czfi1AzrtjfnfCROyWGeDd5IVMKCwsgSmMip9OWijow==" 1840 | }, 1841 | "@types/node": { 1842 | "version": "17.0.33", 1843 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.33.tgz", 1844 | "integrity": "sha512-miWq2m2FiQZmaHfdZNcbpp9PuXg34W5JZ5CrJ/BaS70VuhoJENBEQybeiYSaPBRNq6KQGnjfEnc/F3PN++D+XQ==", 1845 | "dev": true 1846 | }, 1847 | "@types/pug": { 1848 | "version": "2.0.6", 1849 | "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", 1850 | "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", 1851 | "dev": true 1852 | }, 1853 | "@types/sass": { 1854 | "version": "1.43.1", 1855 | "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", 1856 | "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", 1857 | "dev": true, 1858 | "requires": { 1859 | "@types/node": "*" 1860 | } 1861 | }, 1862 | "@zerodevx/svelte-toast": { 1863 | "version": "0.7.2", 1864 | "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.7.2.tgz", 1865 | "integrity": "sha512-vWiY6IqsstcOoQ8PFBuFuxgPkj1JFAGhUF9gC7wLx7c5A9SSfdtxWs/39ekGSIeyJK0yqWhTcmzGrCEWSELzDw==" 1866 | }, 1867 | "anymatch": { 1868 | "version": "3.1.2", 1869 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 1870 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 1871 | "dev": true, 1872 | "requires": { 1873 | "normalize-path": "^3.0.0", 1874 | "picomatch": "^2.0.4" 1875 | } 1876 | }, 1877 | "balanced-match": { 1878 | "version": "1.0.2", 1879 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1880 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1881 | "dev": true 1882 | }, 1883 | "binary-extensions": { 1884 | "version": "2.2.0", 1885 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 1886 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 1887 | "dev": true 1888 | }, 1889 | "brace-expansion": { 1890 | "version": "1.1.11", 1891 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1892 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1893 | "dev": true, 1894 | "requires": { 1895 | "balanced-match": "^1.0.0", 1896 | "concat-map": "0.0.1" 1897 | } 1898 | }, 1899 | "braces": { 1900 | "version": "3.0.2", 1901 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 1902 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 1903 | "dev": true, 1904 | "requires": { 1905 | "fill-range": "^7.0.1" 1906 | } 1907 | }, 1908 | "buffer-crc32": { 1909 | "version": "0.2.13", 1910 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 1911 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 1912 | "dev": true 1913 | }, 1914 | "callsites": { 1915 | "version": "3.1.0", 1916 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 1917 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 1918 | "dev": true 1919 | }, 1920 | "chokidar": { 1921 | "version": "3.5.3", 1922 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 1923 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 1924 | "dev": true, 1925 | "requires": { 1926 | "anymatch": "~3.1.2", 1927 | "braces": "~3.0.2", 1928 | "fsevents": "~2.3.2", 1929 | "glob-parent": "~5.1.2", 1930 | "is-binary-path": "~2.1.0", 1931 | "is-glob": "~4.0.1", 1932 | "normalize-path": "~3.0.0", 1933 | "readdirp": "~3.6.0" 1934 | } 1935 | }, 1936 | "concat-map": { 1937 | "version": "0.0.1", 1938 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1939 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 1940 | "dev": true 1941 | }, 1942 | "crelt": { 1943 | "version": "1.0.5", 1944 | "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", 1945 | "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" 1946 | }, 1947 | "debug": { 1948 | "version": "4.3.4", 1949 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1950 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1951 | "dev": true, 1952 | "requires": { 1953 | "ms": "2.1.2" 1954 | } 1955 | }, 1956 | "deepmerge": { 1957 | "version": "4.2.2", 1958 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 1959 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", 1960 | "dev": true 1961 | }, 1962 | "detect-indent": { 1963 | "version": "6.1.0", 1964 | "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", 1965 | "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", 1966 | "dev": true 1967 | }, 1968 | "es6-promise": { 1969 | "version": "3.3.1", 1970 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", 1971 | "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", 1972 | "dev": true 1973 | }, 1974 | "esbuild": { 1975 | "version": "0.14.39", 1976 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", 1977 | "integrity": "sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ==", 1978 | "dev": true, 1979 | "requires": { 1980 | "esbuild-android-64": "0.14.39", 1981 | "esbuild-android-arm64": "0.14.39", 1982 | "esbuild-darwin-64": "0.14.39", 1983 | "esbuild-darwin-arm64": "0.14.39", 1984 | "esbuild-freebsd-64": "0.14.39", 1985 | "esbuild-freebsd-arm64": "0.14.39", 1986 | "esbuild-linux-32": "0.14.39", 1987 | "esbuild-linux-64": "0.14.39", 1988 | "esbuild-linux-arm": "0.14.39", 1989 | "esbuild-linux-arm64": "0.14.39", 1990 | "esbuild-linux-mips64le": "0.14.39", 1991 | "esbuild-linux-ppc64le": "0.14.39", 1992 | "esbuild-linux-riscv64": "0.14.39", 1993 | "esbuild-linux-s390x": "0.14.39", 1994 | "esbuild-netbsd-64": "0.14.39", 1995 | "esbuild-openbsd-64": "0.14.39", 1996 | "esbuild-sunos-64": "0.14.39", 1997 | "esbuild-windows-32": "0.14.39", 1998 | "esbuild-windows-64": "0.14.39", 1999 | "esbuild-windows-arm64": "0.14.39" 2000 | } 2001 | }, 2002 | "esbuild-android-64": { 2003 | "version": "0.14.39", 2004 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", 2005 | "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", 2006 | "dev": true, 2007 | "optional": true 2008 | }, 2009 | "esbuild-android-arm64": { 2010 | "version": "0.14.39", 2011 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", 2012 | "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", 2013 | "dev": true, 2014 | "optional": true 2015 | }, 2016 | "esbuild-darwin-64": { 2017 | "version": "0.14.39", 2018 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", 2019 | "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", 2020 | "dev": true, 2021 | "optional": true 2022 | }, 2023 | "esbuild-darwin-arm64": { 2024 | "version": "0.14.39", 2025 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", 2026 | "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", 2027 | "dev": true, 2028 | "optional": true 2029 | }, 2030 | "esbuild-freebsd-64": { 2031 | "version": "0.14.39", 2032 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", 2033 | "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", 2034 | "dev": true, 2035 | "optional": true 2036 | }, 2037 | "esbuild-freebsd-arm64": { 2038 | "version": "0.14.39", 2039 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", 2040 | "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", 2041 | "dev": true, 2042 | "optional": true 2043 | }, 2044 | "esbuild-linux-32": { 2045 | "version": "0.14.39", 2046 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", 2047 | "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", 2048 | "dev": true, 2049 | "optional": true 2050 | }, 2051 | "esbuild-linux-64": { 2052 | "version": "0.14.39", 2053 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", 2054 | "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", 2055 | "dev": true, 2056 | "optional": true 2057 | }, 2058 | "esbuild-linux-arm": { 2059 | "version": "0.14.39", 2060 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", 2061 | "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", 2062 | "dev": true, 2063 | "optional": true 2064 | }, 2065 | "esbuild-linux-arm64": { 2066 | "version": "0.14.39", 2067 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", 2068 | "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", 2069 | "dev": true, 2070 | "optional": true 2071 | }, 2072 | "esbuild-linux-mips64le": { 2073 | "version": "0.14.39", 2074 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", 2075 | "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", 2076 | "dev": true, 2077 | "optional": true 2078 | }, 2079 | "esbuild-linux-ppc64le": { 2080 | "version": "0.14.39", 2081 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", 2082 | "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", 2083 | "dev": true, 2084 | "optional": true 2085 | }, 2086 | "esbuild-linux-riscv64": { 2087 | "version": "0.14.39", 2088 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", 2089 | "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", 2090 | "dev": true, 2091 | "optional": true 2092 | }, 2093 | "esbuild-linux-s390x": { 2094 | "version": "0.14.39", 2095 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", 2096 | "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", 2097 | "dev": true, 2098 | "optional": true 2099 | }, 2100 | "esbuild-netbsd-64": { 2101 | "version": "0.14.39", 2102 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", 2103 | "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", 2104 | "dev": true, 2105 | "optional": true 2106 | }, 2107 | "esbuild-openbsd-64": { 2108 | "version": "0.14.39", 2109 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", 2110 | "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", 2111 | "dev": true, 2112 | "optional": true 2113 | }, 2114 | "esbuild-sunos-64": { 2115 | "version": "0.14.39", 2116 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", 2117 | "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", 2118 | "dev": true, 2119 | "optional": true 2120 | }, 2121 | "esbuild-windows-32": { 2122 | "version": "0.14.39", 2123 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", 2124 | "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", 2125 | "dev": true, 2126 | "optional": true 2127 | }, 2128 | "esbuild-windows-64": { 2129 | "version": "0.14.39", 2130 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", 2131 | "integrity": "sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow==", 2132 | "dev": true, 2133 | "optional": true 2134 | }, 2135 | "esbuild-windows-arm64": { 2136 | "version": "0.14.39", 2137 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", 2138 | "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", 2139 | "dev": true, 2140 | "optional": true 2141 | }, 2142 | "estree-walker": { 2143 | "version": "2.0.2", 2144 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 2145 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 2146 | "dev": true 2147 | }, 2148 | "fast-glob": { 2149 | "version": "3.2.11", 2150 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", 2151 | "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", 2152 | "dev": true, 2153 | "requires": { 2154 | "@nodelib/fs.stat": "^2.0.2", 2155 | "@nodelib/fs.walk": "^1.2.3", 2156 | "glob-parent": "^5.1.2", 2157 | "merge2": "^1.3.0", 2158 | "micromatch": "^4.0.4" 2159 | } 2160 | }, 2161 | "fastq": { 2162 | "version": "1.13.0", 2163 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", 2164 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", 2165 | "dev": true, 2166 | "requires": { 2167 | "reusify": "^1.0.4" 2168 | } 2169 | }, 2170 | "fill-range": { 2171 | "version": "7.0.1", 2172 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 2173 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 2174 | "dev": true, 2175 | "requires": { 2176 | "to-regex-range": "^5.0.1" 2177 | } 2178 | }, 2179 | "formatter": { 2180 | "version": "file:../formatter/pkg" 2181 | }, 2182 | "fs.realpath": { 2183 | "version": "1.0.0", 2184 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 2185 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 2186 | "dev": true 2187 | }, 2188 | "fsevents": { 2189 | "version": "2.3.2", 2190 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 2191 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 2192 | "dev": true, 2193 | "optional": true 2194 | }, 2195 | "function-bind": { 2196 | "version": "1.1.1", 2197 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 2198 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 2199 | "dev": true 2200 | }, 2201 | "glob": { 2202 | "version": "7.2.2", 2203 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.2.tgz", 2204 | "integrity": "sha512-NzDgHDiJwKYByLrL5lONmQFpK/2G78SMMfo+E9CuGlX4IkvfKDsiQSNPwAYxEy+e6p7ZQ3uslSLlwlJcqezBmQ==", 2205 | "dev": true, 2206 | "requires": { 2207 | "fs.realpath": "^1.0.0", 2208 | "inflight": "^1.0.4", 2209 | "inherits": "2", 2210 | "minimatch": "^3.1.1", 2211 | "once": "^1.3.0", 2212 | "path-is-absolute": "^1.0.0" 2213 | } 2214 | }, 2215 | "glob-parent": { 2216 | "version": "5.1.2", 2217 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 2218 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 2219 | "dev": true, 2220 | "requires": { 2221 | "is-glob": "^4.0.1" 2222 | } 2223 | }, 2224 | "graceful-fs": { 2225 | "version": "4.2.10", 2226 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 2227 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", 2228 | "dev": true 2229 | }, 2230 | "has": { 2231 | "version": "1.0.3", 2232 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 2233 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 2234 | "dev": true, 2235 | "requires": { 2236 | "function-bind": "^1.1.1" 2237 | } 2238 | }, 2239 | "import-fresh": { 2240 | "version": "3.3.0", 2241 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 2242 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 2243 | "dev": true, 2244 | "requires": { 2245 | "parent-module": "^1.0.0", 2246 | "resolve-from": "^4.0.0" 2247 | } 2248 | }, 2249 | "inflight": { 2250 | "version": "1.0.6", 2251 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 2252 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 2253 | "dev": true, 2254 | "requires": { 2255 | "once": "^1.3.0", 2256 | "wrappy": "1" 2257 | } 2258 | }, 2259 | "inherits": { 2260 | "version": "2.0.4", 2261 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 2262 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 2263 | "dev": true 2264 | }, 2265 | "is-binary-path": { 2266 | "version": "2.1.0", 2267 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 2268 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 2269 | "dev": true, 2270 | "requires": { 2271 | "binary-extensions": "^2.0.0" 2272 | } 2273 | }, 2274 | "is-core-module": { 2275 | "version": "2.9.0", 2276 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", 2277 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", 2278 | "dev": true, 2279 | "requires": { 2280 | "has": "^1.0.3" 2281 | } 2282 | }, 2283 | "is-extglob": { 2284 | "version": "2.1.1", 2285 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 2286 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 2287 | "dev": true 2288 | }, 2289 | "is-glob": { 2290 | "version": "4.0.3", 2291 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 2292 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 2293 | "dev": true, 2294 | "requires": { 2295 | "is-extglob": "^2.1.1" 2296 | } 2297 | }, 2298 | "is-number": { 2299 | "version": "7.0.0", 2300 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2301 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 2302 | "dev": true 2303 | }, 2304 | "kleur": { 2305 | "version": "4.1.4", 2306 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", 2307 | "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", 2308 | "dev": true 2309 | }, 2310 | "lz-string": { 2311 | "version": "1.4.4", 2312 | "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", 2313 | "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=" 2314 | }, 2315 | "magic-string": { 2316 | "version": "0.26.2", 2317 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz", 2318 | "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==", 2319 | "dev": true, 2320 | "requires": { 2321 | "sourcemap-codec": "^1.4.8" 2322 | } 2323 | }, 2324 | "merge2": { 2325 | "version": "1.4.1", 2326 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 2327 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 2328 | "dev": true 2329 | }, 2330 | "micromatch": { 2331 | "version": "4.0.5", 2332 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", 2333 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 2334 | "dev": true, 2335 | "requires": { 2336 | "braces": "^3.0.2", 2337 | "picomatch": "^2.3.1" 2338 | } 2339 | }, 2340 | "min-indent": { 2341 | "version": "1.0.1", 2342 | "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", 2343 | "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", 2344 | "dev": true 2345 | }, 2346 | "minimatch": { 2347 | "version": "3.1.2", 2348 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 2349 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 2350 | "dev": true, 2351 | "requires": { 2352 | "brace-expansion": "^1.1.7" 2353 | } 2354 | }, 2355 | "minimist": { 2356 | "version": "1.2.6", 2357 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 2358 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", 2359 | "dev": true 2360 | }, 2361 | "mkdirp": { 2362 | "version": "0.5.6", 2363 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 2364 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 2365 | "dev": true, 2366 | "requires": { 2367 | "minimist": "^1.2.6" 2368 | } 2369 | }, 2370 | "mri": { 2371 | "version": "1.2.0", 2372 | "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", 2373 | "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", 2374 | "dev": true 2375 | }, 2376 | "ms": { 2377 | "version": "2.1.2", 2378 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2379 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 2380 | "dev": true 2381 | }, 2382 | "nanoid": { 2383 | "version": "3.3.4", 2384 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 2385 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 2386 | "dev": true 2387 | }, 2388 | "normalize-path": { 2389 | "version": "3.0.0", 2390 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 2391 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 2392 | "dev": true 2393 | }, 2394 | "once": { 2395 | "version": "1.4.0", 2396 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2397 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2398 | "dev": true, 2399 | "requires": { 2400 | "wrappy": "1" 2401 | } 2402 | }, 2403 | "parent-module": { 2404 | "version": "1.0.1", 2405 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2406 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2407 | "dev": true, 2408 | "requires": { 2409 | "callsites": "^3.0.0" 2410 | } 2411 | }, 2412 | "path-is-absolute": { 2413 | "version": "1.0.1", 2414 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2415 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2416 | "dev": true 2417 | }, 2418 | "path-parse": { 2419 | "version": "1.0.7", 2420 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 2421 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 2422 | "dev": true 2423 | }, 2424 | "picocolors": { 2425 | "version": "1.0.0", 2426 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 2427 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 2428 | "dev": true 2429 | }, 2430 | "picomatch": { 2431 | "version": "2.3.1", 2432 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 2433 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 2434 | "dev": true 2435 | }, 2436 | "postcss": { 2437 | "version": "8.4.13", 2438 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", 2439 | "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", 2440 | "dev": true, 2441 | "requires": { 2442 | "nanoid": "^3.3.3", 2443 | "picocolors": "^1.0.0", 2444 | "source-map-js": "^1.0.2" 2445 | } 2446 | }, 2447 | "queue-microtask": { 2448 | "version": "1.2.3", 2449 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2450 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2451 | "dev": true 2452 | }, 2453 | "readdirp": { 2454 | "version": "3.6.0", 2455 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2456 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2457 | "dev": true, 2458 | "requires": { 2459 | "picomatch": "^2.2.1" 2460 | } 2461 | }, 2462 | "resolve": { 2463 | "version": "1.22.0", 2464 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", 2465 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", 2466 | "dev": true, 2467 | "requires": { 2468 | "is-core-module": "^2.8.1", 2469 | "path-parse": "^1.0.7", 2470 | "supports-preserve-symlinks-flag": "^1.0.0" 2471 | } 2472 | }, 2473 | "resolve-from": { 2474 | "version": "4.0.0", 2475 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2476 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2477 | "dev": true 2478 | }, 2479 | "reusify": { 2480 | "version": "1.0.4", 2481 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2482 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2483 | "dev": true 2484 | }, 2485 | "rimraf": { 2486 | "version": "2.7.1", 2487 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", 2488 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", 2489 | "dev": true, 2490 | "requires": { 2491 | "glob": "^7.1.3" 2492 | } 2493 | }, 2494 | "rollup": { 2495 | "version": "2.73.0", 2496 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.73.0.tgz", 2497 | "integrity": "sha512-h/UngC3S4Zt28mB3g0+2YCMegT5yoftnQplwzPqGZcKvlld5e+kT/QRmJiL+qxGyZKOYpgirWGdLyEO1b0dpLQ==", 2498 | "dev": true, 2499 | "requires": { 2500 | "fsevents": "~2.3.2" 2501 | } 2502 | }, 2503 | "run-parallel": { 2504 | "version": "1.2.0", 2505 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2506 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2507 | "dev": true, 2508 | "requires": { 2509 | "queue-microtask": "^1.2.2" 2510 | } 2511 | }, 2512 | "sade": { 2513 | "version": "1.8.1", 2514 | "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", 2515 | "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", 2516 | "dev": true, 2517 | "requires": { 2518 | "mri": "^1.1.0" 2519 | } 2520 | }, 2521 | "sander": { 2522 | "version": "0.5.1", 2523 | "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", 2524 | "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=", 2525 | "dev": true, 2526 | "requires": { 2527 | "es6-promise": "^3.1.2", 2528 | "graceful-fs": "^4.1.3", 2529 | "mkdirp": "^0.5.1", 2530 | "rimraf": "^2.5.2" 2531 | } 2532 | }, 2533 | "sorcery": { 2534 | "version": "0.10.0", 2535 | "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", 2536 | "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=", 2537 | "dev": true, 2538 | "requires": { 2539 | "buffer-crc32": "^0.2.5", 2540 | "minimist": "^1.2.0", 2541 | "sander": "^0.5.0", 2542 | "sourcemap-codec": "^1.3.0" 2543 | } 2544 | }, 2545 | "source-map-js": { 2546 | "version": "1.0.2", 2547 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 2548 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 2549 | "dev": true 2550 | }, 2551 | "sourcemap-codec": { 2552 | "version": "1.4.8", 2553 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 2554 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 2555 | "dev": true 2556 | }, 2557 | "strip-indent": { 2558 | "version": "3.0.0", 2559 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", 2560 | "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", 2561 | "dev": true, 2562 | "requires": { 2563 | "min-indent": "^1.0.0" 2564 | } 2565 | }, 2566 | "style-mod": { 2567 | "version": "4.0.0", 2568 | "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", 2569 | "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==" 2570 | }, 2571 | "supports-preserve-symlinks-flag": { 2572 | "version": "1.0.0", 2573 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 2574 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 2575 | "dev": true 2576 | }, 2577 | "svelte": { 2578 | "version": "3.48.0", 2579 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.48.0.tgz", 2580 | "integrity": "sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==", 2581 | "dev": true 2582 | }, 2583 | "svelte-check": { 2584 | "version": "2.7.1", 2585 | "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.7.1.tgz", 2586 | "integrity": "sha512-vHVu2+SQ6ibt77iTQaq2oiOjBgGL48qqcg0ZdEOsP5pPOjgeyR9QbnaEdzdBs9nsVYBc/42haKtzb2uFqS8GVw==", 2587 | "dev": true, 2588 | "requires": { 2589 | "@jridgewell/trace-mapping": "^0.3.9", 2590 | "chokidar": "^3.4.1", 2591 | "fast-glob": "^3.2.7", 2592 | "import-fresh": "^3.2.1", 2593 | "picocolors": "^1.0.0", 2594 | "sade": "^1.7.4", 2595 | "svelte-preprocess": "^4.0.0", 2596 | "typescript": "*" 2597 | } 2598 | }, 2599 | "svelte-hmr": { 2600 | "version": "0.14.11", 2601 | "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.11.tgz", 2602 | "integrity": "sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==", 2603 | "dev": true, 2604 | "requires": {} 2605 | }, 2606 | "svelte-loading-spinners": { 2607 | "version": "0.1.7", 2608 | "resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.1.7.tgz", 2609 | "integrity": "sha512-EKCId1DjVL2RSUVJJsvtNcqQHox03XIgh4xh/4p7r6ST7d8mut6INY9/LqK4A17PFU64+3quZmqiSfOlf480CA==" 2610 | }, 2611 | "svelte-preprocess": { 2612 | "version": "4.10.6", 2613 | "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.6.tgz", 2614 | "integrity": "sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ==", 2615 | "dev": true, 2616 | "requires": { 2617 | "@types/pug": "^2.0.4", 2618 | "@types/sass": "^1.16.0", 2619 | "detect-indent": "^6.0.0", 2620 | "magic-string": "^0.25.7", 2621 | "sorcery": "^0.10.0", 2622 | "strip-indent": "^3.0.0" 2623 | }, 2624 | "dependencies": { 2625 | "magic-string": { 2626 | "version": "0.25.9", 2627 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", 2628 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", 2629 | "dev": true, 2630 | "requires": { 2631 | "sourcemap-codec": "^1.4.8" 2632 | } 2633 | } 2634 | } 2635 | }, 2636 | "to-regex-range": { 2637 | "version": "5.0.1", 2638 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2639 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2640 | "dev": true, 2641 | "requires": { 2642 | "is-number": "^7.0.0" 2643 | } 2644 | }, 2645 | "tslib": { 2646 | "version": "2.4.0", 2647 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", 2648 | "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", 2649 | "dev": true 2650 | }, 2651 | "typescript": { 2652 | "version": "4.6.4", 2653 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", 2654 | "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", 2655 | "dev": true 2656 | }, 2657 | "vite": { 2658 | "version": "2.9.9", 2659 | "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", 2660 | "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", 2661 | "dev": true, 2662 | "requires": { 2663 | "esbuild": "^0.14.27", 2664 | "fsevents": "~2.3.2", 2665 | "postcss": "^8.4.13", 2666 | "resolve": "^1.22.0", 2667 | "rollup": "^2.59.0" 2668 | } 2669 | }, 2670 | "w3c-keyname": { 2671 | "version": "2.2.4", 2672 | "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", 2673 | "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" 2674 | }, 2675 | "wrappy": { 2676 | "version": "1.0.2", 2677 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2678 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2679 | "dev": true 2680 | } 2681 | } 2682 | } 2683 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend-next", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "check": "svelte-check --tsconfig ./tsconfig.json" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^1.0.0-next.30", 14 | "@tsconfig/svelte": "^2.0.1", 15 | "svelte": "^3.44.0", 16 | "svelte-check": "^2.2.7", 17 | "svelte-preprocess": "^4.9.8", 18 | "tslib": "^2.3.1", 19 | "typescript": "^4.5.4", 20 | "vite": "^2.9.9" 21 | }, 22 | "dependencies": { 23 | "@codemirror/basic-setup": "^0.20.0", 24 | "@codemirror/lang-rust": "^0.20.0", 25 | "@codemirror/theme-one-dark": "^0.20.0", 26 | "@types/lz-string": "^1.3.34", 27 | "@zerodevx/svelte-toast": "^0.7.2", 28 | "lz-string": "^1.4.4", 29 | "svelte-loading-spinners": "^0.1.7", 30 | "formatter": "file:../formatter/pkg" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /frontend/public/global.css: -------------------------------------------------------------------------------- 1 | /* Box sizing rules */ 2 | *, 3 | *::before, 4 | *::after { 5 | box-sizing: border-box; 6 | } 7 | 8 | /* Show focus ring only when navigated with keyboard */ 9 | button:focus:not(:focus-visible) { 10 | outline: none; 11 | } 12 | 13 | /* Remove default margin */ 14 | body, 15 | h1, 16 | h2, 17 | h3, 18 | h4, 19 | p, 20 | figure, 21 | blockquote, 22 | dl, 23 | dd, 24 | ul { 25 | margin: 0; 26 | } 27 | 28 | :root {} 29 | 30 | html { 31 | height: 100%; 32 | min-height: 100%; 33 | } 34 | 35 | body { 36 | text-rendering: optimizeSpeed; 37 | line-height: 1.25; 38 | height: 100%; 39 | min-height: 100%; 40 | transition: color 200ms, background-color 200ms; 41 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; 42 | } 43 | 44 | #app { 45 | height: 100%; 46 | min-height: 100%; 47 | } 48 | 49 | body, 50 | body * { 51 | overflow-wrap: break-word; 52 | min-width: 0; 53 | } 54 | 55 | /* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ 56 | ul, 57 | ol { 58 | list-style: none; 59 | padding: 0; 60 | } 61 | 62 | html:focus-within { 63 | scroll-behavior: smooth; 64 | } 65 | 66 | /* A elements that don't have a class get default styles */ 67 | a { 68 | text-decoration-skip-ink: auto; 69 | } 70 | 71 | /* Make images easier to work with */ 72 | img, 73 | picture, 74 | iframe { 75 | max-width: 100%; 76 | display: block; 77 | } 78 | 79 | /* Inherit fonts for inputs and buttons */ 80 | input, 81 | button, 82 | textarea, 83 | select { 84 | font: inherit; 85 | } 86 | 87 | /* Remove all animations and transitions for people that prefer not to see them */ 88 | @media (prefers-reduced-motion: reduce) { 89 | html:focus-within { 90 | scroll-behavior: auto; 91 | } 92 | 93 | *, 94 | *::before, 95 | *::after { 96 | animation-duration: 0.01ms !important; 97 | animation-iteration-count: 1 !important; 98 | transition-duration: 0.01ms !important; 99 | scroll-behavior: auto !important; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /frontend/src/ActionButton.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 37 | -------------------------------------------------------------------------------- /frontend/src/App.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 | 42 | -------------------------------------------------------------------------------- /frontend/src/ButtonPanel.svelte: -------------------------------------------------------------------------------- 1 | 58 | 59 |
60 | Build 🛠️ 63 | Run ▶️ 66 | Share 🪄 67 | About TypeRust 68 |
69 | 70 | 85 | -------------------------------------------------------------------------------- /frontend/src/Editor.svelte: -------------------------------------------------------------------------------- 1 | 123 | 124 |
125 |
126 |
127 | {isDarkTheme ? "Light" : "Dark"} 130 | Format 📝 131 |
132 |
133 | 134 | 156 | -------------------------------------------------------------------------------- /frontend/src/Error.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
{message}
6 | -------------------------------------------------------------------------------- /frontend/src/Output.svelte: -------------------------------------------------------------------------------- 1 | 46 | 47 |
48 | 49 | {#if $loading}
{/if} 50 |
51 | {#if $error != ""} 52 | 53 | {:else} 54 | 55 | {#if message}
56 |
{message}
{/if} 57 | {/if} 58 |
59 |
60 | 61 | 91 | -------------------------------------------------------------------------------- /frontend/src/assets/some.css: -------------------------------------------------------------------------------- 1 | .lol { 2 | font-size: 100px; 3 | } 4 | -------------------------------------------------------------------------------- /frontend/src/assets/svelte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlkiri/typerust/7350ea55a205bf931c50640b802b083908b6cdd6/frontend/src/assets/svelte.png -------------------------------------------------------------------------------- /frontend/src/code.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const code = writable(""); 4 | -------------------------------------------------------------------------------- /frontend/src/const.ts: -------------------------------------------------------------------------------- 1 | export const BUILD_URL = "/api/build"; 2 | export const RUN_URL = "/api/run"; 3 | -------------------------------------------------------------------------------- /frontend/src/loading.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const loading = writable(false); 4 | -------------------------------------------------------------------------------- /frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import App from './App.svelte' 2 | 3 | const app = new App({ 4 | target: document.getElementById('app') 5 | }) 6 | 7 | export default app 8 | -------------------------------------------------------------------------------- /frontend/src/response.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | import type { Fail, ServerResponse, Success } from "./vite-env"; 3 | 4 | export const response = writable>(null); 5 | export const error = writable(""); 6 | -------------------------------------------------------------------------------- /frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | export type Success = { elapsed: number; output?: string }; 5 | export type Fail = string; 6 | export type ResponseType = "Success" | "Error"; 7 | export type ServerResponse = { type: ResponseType; data: Data }; 8 | -------------------------------------------------------------------------------- /frontend/svelte.config.js: -------------------------------------------------------------------------------- 1 | import sveltePreprocess from 'svelte-preprocess' 2 | 3 | export default { 4 | // Consult https://github.com/sveltejs/svelte-preprocess 5 | // for more information about preprocessors 6 | preprocess: sveltePreprocess() 7 | } 8 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "useDefineForClassFields": true, 6 | "module": "esnext", 7 | "resolveJsonModule": true, 8 | "baseUrl": ".", 9 | /** 10 | * Typecheck JS in `.svelte` and `.js` files by default. 11 | * Disable checkJs if you'd like to use dynamic types in JS. 12 | * Note that setting allowJs false does not prevent the use 13 | * of JS in `.svelte` files. 14 | */ 15 | "allowJs": true, 16 | "checkJs": true, 17 | "isolatedModules": true 18 | }, 19 | "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { svelte } from '@sveltejs/vite-plugin-svelte' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [svelte()] 7 | }) 8 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | set dotenv-load := true 2 | set shell := ["bash", "-uc"] 3 | 4 | RUST_LOG := env("RUST_LOG", "debug") 5 | IP_ADDR := env("IP_ADDR", "0.0.0.0:8080") 6 | LOCAL_LOG_ONLY := env("LOCAL_LOG_ONLY", "true") 7 | OTLP_EXPORT_URL := env("OTLP_EXPORT_URL", "") 8 | HONEYCOMB_API_TOKEN := env("HONEYCOMB_API_TOKEN", "") 9 | 10 | build-formatter: 11 | docker buildx build --file formatter/Dockerfile formatter --output formatter/pkg 12 | 13 | frontend-install-deps: 14 | cd frontend && npm ci 15 | 16 | build-frontend: build-formatter 17 | rm -rf server/public/* 18 | mkdir -p server/public 19 | cd frontend && npm run build 20 | cp -r frontend/dist/* server/public 21 | cp -r md/* server/public 22 | 23 | build-frontend-ci: build-formatter frontend-install-deps build-frontend 24 | 25 | build: build-frontend 26 | cargo build --manifest-path server/Cargo.toml 27 | 28 | check: 29 | cargo check --manifest-path server/Cargo.toml 30 | 31 | test: 32 | cargo test --manifest-path server/Cargo.toml 33 | 34 | run-local: build 35 | IP_ADDR={{IP_ADDR}} LOCAL_LOG_ONLY={{LOCAL_LOG_ONLY}} OTLP_EXPORT_URL={{OTLP_EXPORT_URL}} HONEYCOMB_API_TOKEN={{HONEYCOMB_API_TOKEN}} RUST_LOG={{RUST_LOG}},typerust=debug cargo run --manifest-path server/Cargo.toml 36 | 37 | build-image: build-frontend 38 | docker buildx build --tag typerust . 39 | 40 | run: stop 41 | docker run \ 42 | --env RUST_LOG={{RUST_LOG}} \ 43 | --env IP_ADDR={{IP_ADDR}} \ 44 | --env LOCAL_LOG_ONLY={{LOCAL_LOG_ONLY}} \ 45 | --env OTLP_EXPORT_URL={{OTLP_EXPORT_URL}} \ 46 | --env HONEYCOMB_API_TOKEN={{HONEYCOMB_API_TOKEN}} \ 47 | --name playground \ 48 | --publish 8080:8080 typerust 49 | 50 | stop: 51 | docker stop playground || exit 0 52 | 53 | deploy-dev: 54 | fly deploy --config fly.dev.toml 55 | 56 | deploy-prod: 57 | fly deploy --config fly.production.toml 58 | 59 | load-test: 60 | oha -c 100 -n 400 --disable-keepalive --method POST -d 'fn main() { println!("Hello, world!"); }' http://localhost:8080/api/run 61 | -------------------------------------------------------------------------------- /md/about.md: -------------------------------------------------------------------------------- 1 | ## Rust playground 2 | Welcome to **TypeRust**! This is a simple Rust playground where you can build or run your Rust code and share it with others. 3 | 4 | There are a few things to keep in mind before using it: 5 | * Code execution time is limited and if it takes too long to complete it will be interrupted. 6 | * Your program cannot use too much memory. If it exceeds the limit it will be interrupted. 7 | * Since the program runs in a sandbox, it doesn't have access to filesystem and/or network. Of course simply building code is fine. 8 | 9 | ## Environment 10 | 11 | * The code is compiled to `wasm32-wasi` target and is run in a [`wasmtime`](https://github.com/bytecodealliance/wasmtime) instance. 12 | * The latest stable version of Rust with 2021 edition is used. 13 | * There is no way to install crates (yet). 14 | 15 | ## Development 16 | 17 | ### Tech 18 | TypeRust playground is powered by [`Svelte`](https://svelte.dev/) and [CodeMirror](https://codemirror.net/6/) editor on frontend and [`axum`](https://github.com/tokio-rs/axum) (and its ecosystem) on backend. [`wasmtime`](https://github.com/bytecodealliance/wasmtime) is used to create ephemeral WASM virtual machines to run user code. The whole thing is deployed to [Fly.io](https://fly.io/). 19 | 20 | ### Source code 21 | You can find source code on Github: [https://github.com/jlkiri/typerust](https://github.com/jlkiri/typerust). 22 | 23 | ## About the author 24 | This playground was created by [Kirill Vasiltsov](https://www.kirillvasiltsov.com/). 25 | 26 | ### Sponsorship 27 | Currently I (the author) pay for the infrastructure out of my own pocket. It is not much but any help is appreciated. Sponsoring via Github is not available at the moment, but you can use my [PayPal profile](https://paypal.me/jlkiri) if you want to help. Anyone with one-time payment of 10$ or more gets: 28 | 29 | * A huge Thank You from me 30 | * Optional advice on working as a software engineer in Japan 31 | * Optional advice on contributing to OSS projects 32 | 33 | To receive advice contact me at email address on my [personal homepage](https://www.kirillvasiltsov.com/). 34 | -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "typerust" 3 | version = "0.1.0" 4 | edition = "2021" 5 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 6 | 7 | [dependencies] 8 | anyhow = "1.0.57" 9 | async-trait = "0.1.53" 10 | axum = "0.5.4" 11 | axum-extra = { version = "0.3.3", features = ["spa"] } 12 | bytes = "1.1.0" 13 | bytesize = "1.1.0" 14 | cap-std = "3.4.2" 15 | dotenv = "0.15.0" 16 | envy = "0.4.2" 17 | http-body = "0.4.5" 18 | include_dir = { version = "0.7.2", features = ["metadata"] } 19 | mime_guess = "2.0.4" 20 | once_cell = "1.10.0" 21 | opentelemetry = { version = "0.17.0", features = ["tokio", "rt-tokio"] } 22 | opentelemetry-otlp = { version = "0.10.0", features = ["tls"] } 23 | pulldown-cmark = { version = "0.9.1", default-features = false } 24 | serde = "1.0.137" 25 | serde_json = "1.0.81" 26 | tempfile = "3.3.0" 27 | tera = { version = "1.15.0", default-features = false } 28 | thiserror = "1.0" 29 | tokio = { version = "1.18.1", features = ["full"] } 30 | tonic = { version = "0.6.2", features = ["tls-roots"] } 31 | tower-http = { version = "0.3.3", features = [ 32 | "cors", 33 | "fs", 34 | "set-header", 35 | "trace", 36 | ] } 37 | tracing = { version = "0.1.34", features = ["attributes"] } 38 | tracing-opentelemetry = "0.17.2" 39 | tracing-subscriber = { version = "0.3.11", features = ["env-filter", "fmt"] } 40 | url = "2.2.2" 41 | wasi-common = "30.0.1" 42 | wasmtime = { version = "30.0.1", features = ["async"] } 43 | wasmtime-wasi = "30.0.1" 44 | 45 | [target.'cfg(target_os = "linux")'.dependencies] 46 | memfile = "0.2.1" 47 | -------------------------------------------------------------------------------- /server/public/about.md: -------------------------------------------------------------------------------- 1 | ## Rust playground 2 | Welcome to **TypeRust**! This is a simple Rust playground where you can build or run your Rust code and share it with others. 3 | 4 | There are a few things to keep in mind before using it: 5 | * Code execution time is limited and if it takes too long to complete it will be interrupted. 6 | * Your program cannot use too much memory. If it exceeds the limit it will be interrupted. 7 | * Since the program runs in a sandbox, it doesn't have access to filesystem and/or network. Of course simply building code is fine. 8 | 9 | ## Environment 10 | 11 | * The code is compiled to `wasm32-wasi` target and is run in a [`wasmtime`](https://github.com/bytecodealliance/wasmtime) instance. 12 | * The latest stable version of Rust with 2021 edition is used. 13 | * There is no way to install crates (yet). 14 | 15 | ## Development 16 | 17 | ### Tech 18 | TypeRust playground is powered by [`Svelte`](https://svelte.dev/) and [CodeMirror](https://codemirror.net/6/) editor on frontend and [`axum`](https://github.com/tokio-rs/axum) (and its ecosystem) on backend. [`wasmtime`](https://github.com/bytecodealliance/wasmtime) is used to create ephemeral WASM virtual machines to run user code. The whole thing is deployed to [Fly.io](https://fly.io/). 19 | 20 | ### Source code 21 | You can find source code on Github: [https://github.com/jlkiri/typerust](https://github.com/jlkiri/typerust). 22 | 23 | ## About the author 24 | This playground was created by [Kirill Vasiltsov](https://www.kirillvasiltsov.com/). 25 | 26 | ### Sponsorship 27 | Currently I (the author) pay for the infrastructure out of my own pocket. It is not much but any help is appreciated. Sponsoring via Github is not available at the moment, but you can use my [PayPal profile](https://paypal.me/jlkiri) if you want to help. Anyone with one-time payment of 10$ or more gets: 28 | 29 | * A huge Thank You from me 30 | * Optional advice on working as a software engineer in Japan 31 | * Optional advice on contributing to OSS projects 32 | 33 | To receive advice contact me at email address on my [personal homepage](https://www.kirillvasiltsov.com/). 34 | -------------------------------------------------------------------------------- /server/public/assets/formatter_bg.1471ca7a.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlkiri/typerust/7350ea55a205bf931c50640b802b083908b6cdd6/server/public/assets/formatter_bg.1471ca7a.wasm -------------------------------------------------------------------------------- /server/public/assets/index.75371d95.css: -------------------------------------------------------------------------------- 1 | ._toastItem.svelte-5er0t9{width:var(--toastWidth, 16rem);height:var(--toastHeight, auto);min-height:var(--toastMinHeight, 3.5rem);margin:var(--toastMargin, 0 0 .5rem 0);padding:var(--toastPadding, 0);background:var(--toastBackground, rgba(66, 66, 66, .9));color:var(--toastColor, #fff);box-shadow:var( --toastBoxShadow, 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -1px rgba(0, 0, 0, .06) );border:var(--toastBorder, none);border-radius:var(--toastBorderRadius, .125rem);position:relative;display:flex;flex-direction:row;align-items:center;overflow:hidden;will-change:transform,opacity;-webkit-tap-highlight-color:transparent}._toastMsg.svelte-5er0t9{padding:var(--toastMsgPadding, .75rem .5rem);flex:1 1 0%}.pe.svelte-5er0t9,._toastMsg.svelte-5er0t9 a{pointer-events:auto}._toastBtn.svelte-5er0t9{width:2rem;height:100%;font:1rem sans-serif;display:flex;align-items:center;justify-content:center;cursor:pointer;outline:none}._toastBar.svelte-5er0t9{top:var(--toastBarTop, auto);right:var(--toastBarRight, auto);bottom:var(--toastBarBottom, 0);left:var(--toastBarLeft, 0);height:var(--toastBarHeight, 6px);width:var(--toastBarWidth, 100%);position:absolute;display:block;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;background:transparent;pointer-events:none}._toastBar.svelte-5er0t9::-webkit-progress-bar{background:transparent}._toastBar.svelte-5er0t9::-webkit-progress-value{background:var(--toastProgressBackground, var(--toastBarBackground, rgba(33, 150, 243, .75)))}._toastBar.svelte-5er0t9::-moz-progress-bar{background:var(--toastProgressBackground, var(--toastBarBackground, rgba(33, 150, 243, .75)))}._toastContainer.svelte-yh90az{top:var(--toastContainerTop, 1.5rem);right:var(--toastContainerRight, 2rem);bottom:var(--toastContainerBottom, auto);left:var(--toastContainerLeft, auto);position:fixed;margin:0;padding:0;list-style-type:none;pointer-events:none;z-index:var(--toastContainerZIndex, 9999)}button.svelte-b5b6b1{padding:.4em .8em;border-radius:5px;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;background:#ffffff;border:2px solid rgb(51,47,59);color:#000;font-size:1.1rem;transition:.2s;filter:brightness(.9);font-weight:700}button.dark.svelte-b5b6b1{background:#322d3d;border:2px solid rgb(109,101,127);color:#fff}button.svelte-b5b6b1:disabled{filter:grayscale() brightness(.6)}button.svelte-b5b6b1:hover{cursor:pointer;filter:brightness(1.1)}.editor-wrapper.svelte-1jwpmve.svelte-1jwpmve{position:relative;flex:1}.editor.svelte-1jwpmve.svelte-1jwpmve{flex:1;height:100%}.editor-wrapper.svelte-1jwpmve .toggle.svelte-1jwpmve{position:absolute;top:1em;right:1em;color:#fff}.cm-editor{font-size:1rem}.circle.svelte-14upwad{height:var(--size);width:var(--size);border-color:var(--color) transparent var(--color) var(--color);border-width:calc(var(--size) / 15);border-style:solid;border-image:initial;border-radius:50%;animation:var(--duration) linear 0s infinite normal none running svelte-14upwad-rotate}@keyframes svelte-14upwad-rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.circle.svelte-1vclic6{width:var(--size);height:var(--size);box-sizing:border-box;position:relative;border:3px solid transparent;border-top-color:var(--colorOuter);border-radius:50%;animation:svelte-1vclic6-circleSpin var(--durationOuter) linear infinite}.circle.svelte-1vclic6:before,.circle.svelte-1vclic6:after{content:"";box-sizing:border-box;position:absolute;border:3px solid transparent;border-radius:50%}.circle.svelte-1vclic6:after{border-top-color:var(--colorInner);top:9px;left:9px;right:9px;bottom:9px;animation:svelte-1vclic6-circleSpin var(--durationInner) linear infinite}.circle.svelte-1vclic6:before{border-top-color:var(--colorCenter);top:3px;left:3px;right:3px;bottom:3px;animation:svelte-1vclic6-circleSpin var(--durationCenter) linear infinite}@keyframes svelte-1vclic6-circleSpin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.wrapper.svelte-1vf8im1{width:var(--size);height:var(--size);display:flex;justify-content:center;align-items:center;line-height:0;box-sizing:border-box}.inner.svelte-1vf8im1{transform:scale(calc(var(--floatSize) / 52))}.ball-container.svelte-1vf8im1{animation:svelte-1vf8im1-ballTwo var(--duration) infinite;width:44px;height:44px;flex-shrink:0;position:relative}.single-ball.svelte-1vf8im1{width:44px;height:44px;position:absolute}.ball.svelte-1vf8im1{width:20px;height:20px;border-radius:50%;position:absolute;animation:svelte-1vf8im1-ballOne var(--duration) infinite ease}.ball-top-left.svelte-1vf8im1{background-color:var(--ballTopLeftColor);top:0;left:0}.ball-top-right.svelte-1vf8im1{background-color:var(--ballTopRightColor);top:0;left:24px}.ball-bottom-left.svelte-1vf8im1{background-color:var(--ballBottomLeftColor);top:24px;left:0}.ball-bottom-right.svelte-1vf8im1{background-color:var(--ballBottomRightColor);top:24px;left:24px}@keyframes svelte-1vf8im1-ballOne{0%{position:absolute}50%{top:12px;left:12px;position:absolute;opacity:.5}to{position:absolute}}@keyframes svelte-1vf8im1-ballTwo{0%{transform:rotate(0) scale(1)}50%{transform:rotate(360deg) scale(1.3)}to{transform:rotate(720deg) scale(1)}}.wrapper.svelte-h1a2xs{position:relative;width:var(--size);height:var(--size)}.circle.svelte-h1a2xs{position:absolute;width:var(--size);height:var(--size);background-color:var(--color);border-radius:100%;opacity:.6;top:0;left:0;animation-fill-mode:both;animation-name:svelte-h1a2xs-bounce!important}@keyframes svelte-h1a2xs-bounce{0%,to{transform:scale(0)}50%{transform:scale(1)}}.svelte-1exboqr{overflow:hidden;position:relative;text-indent:-9999px;display:inline-block;background:#f86;border-radius:50%;transform:rotate(90deg);transform-origin:50% 50%;animation:svelte-1exboqr-plus-loader-background var(--duration) infinite ease-in-out}.svelte-1exboqr:after{background:#f86;border-radius:50% 0 0 50%;content:"";position:absolute;right:50%;top:0;width:50%;height:100%;transform-origin:100% 50%;animation:svelte-1exboqr-plus-loader-top var(--duration) infinite linear}.svelte-1exboqr:before{background:#fc6;border-radius:50% 0 0 50%;content:"";position:absolute;right:50%;top:0;width:50%;height:100%;transform-origin:100% 50%;animation:svelte-1exboqr-plus-loader-bottom var(--duration) infinite linear}@keyframes svelte-1exboqr-plus-loader-top{2.5%{background:#f86;transform:rotateY(0);animation-timing-function:ease-in}13.75%{background:#ff430d;transform:rotateY(90deg);animation-timing-function:step-start}13.76%{background:#ffae0d;transform:rotateY(90deg);animation-timing-function:ease-out}25%{background:#fc6;transform:rotateY(180deg)}27.5%{background:#fc6;transform:rotateY(180deg);animation-timing-function:ease-in}41.25%{background:#ffae0d;transform:rotateY(90deg);animation-timing-function:step-start}41.26%{background:#2cc642;transform:rotateY(90deg);animation-timing-function:ease-out}50%{background:#6d7;transform:rotateY(0)}52.5%{background:#6d7;transform:rotateY(0);animation-timing-function:ease-in}63.75%{background:#2cc642;transform:rotateY(90deg);animation-timing-function:step-start}63.76%{background:#1386d2;transform:rotateY(90deg);animation-timing-function:ease-out}75%{background:#4ae;transform:rotateY(180deg)}77.5%{background:#4ae;transform:rotateY(180deg);animation-timing-function:ease-in}91.25%{background:#1386d2;transform:rotateY(90deg);animation-timing-function:step-start}91.26%{background:#ff430d;transform:rotateY(90deg);animation-timing-function:ease-in}to{background:#f86;transform:rotateY(0);animation-timing-function:step-start}}@keyframes svelte-1exboqr-plus-loader-bottom{0%{background:#fc6;animation-timing-function:step-start}50%{background:#fc6;animation-timing-function:step-start}75%{background:#4ae;animation-timing-function:step-start}to{background:#4ae;animation-timing-function:step-start}}@keyframes svelte-1exboqr-plus-loader-background{0%{background:#f86;transform:rotate(180deg)}25%{background:#f86;transform:rotate(180deg);animation-timing-function:step-start}27.5%{background:#6d7;transform:rotate(90deg)}50%{background:#6d7;transform:rotate(90deg);animation-timing-function:step-start}52.5%{background:#6d7;transform:rotate(0)}75%{background:#6d7;transform:rotate(0);animation-timing-function:step-start}77.5%{background:#f86;transform:rotate(270deg)}to{background:#f86;transform:rotate(270deg);animation-timing-function:step-start}}.wrapper.svelte-9juun5{width:var(--size);height:var(--size)}.circle.svelte-9juun5{width:var(--size);height:var(--size);background-color:var(--color);animation-duration:var(--duration);border-radius:100%;display:inline-block;animation:svelte-9juun5-scaleOut var(--duration) ease-in-out infinite}@keyframes svelte-9juun5-scaleOut{0%{transform:scale(0)}to{transform:scale(1);opacity:0}}.wrapper.svelte-1wp57lu{width:var(--size);height:var(--stroke);transform:scale(calc(var(--floatSize) / 75));display:flex;justify-content:center;align-items:center}.line.svelte-1wp57lu{width:var(--size);height:var(--stroke);background:var(--color);border-radius:var(--stroke);transform-origin:center center;animation:svelte-1wp57lu-spineLine var(--duration) ease infinite}@keyframes svelte-1wp57lu-spineLine{0%{transform:rotate(-20deg);height:5px;width:75px}5%{height:5px;width:75px}30%{transform:rotate(380deg);height:5px;width:75px}40%{transform:rotate(360deg);height:5px;width:75px}55%{transform:rotate(0);height:5px;width:5px}65%{transform:rotate(0);height:5px;width:85px}68%{transform:rotate(0);height:5px}75%{transform:rotate(0);height:5px;width:1px}78%{height:5px;width:5px}90%{height:5px;width:75px;transform:rotate(0)}99%,to{height:5px;width:75px;transform:rotate(-20deg)}}.wrapper.svelte-1uxpkwt{height:var(--size);width:var(--size);display:inline-block;text-align:center;font-size:10px}.rect.svelte-1uxpkwt{height:100%;width:10%;display:inline-block;margin-right:4px;background-color:var(--color);animation:svelte-1uxpkwt-stretch var(--duration) ease-in-out infinite}@keyframes svelte-1uxpkwt-stretch{0%,40%,to{transform:scaleY(.4)}20%{transform:scaleY(1)}}.wrapper.svelte-vhcw6{height:calc(var(--size) / 15);width:calc(var(--size) * 2);background-color:var(--rgba);position:relative;overflow:hidden;background-clip:padding-box}.lines.svelte-vhcw6{height:calc(var(--size) / 15);background-color:var(--color)}.small-lines.svelte-vhcw6{position:absolute;overflow:hidden;background-clip:padding-box;display:block;border-radius:2px;will-change:left,right;animation-fill-mode:forwards}.small-lines.\31.svelte-vhcw6{animation:var(--duration) cubic-bezier(.65,.815,.735,.395) 0s infinite normal none running svelte-vhcw6-long}.small-lines.\32.svelte-vhcw6{animation:var(--duration) cubic-bezier(.165,.84,.44,1) calc((var(--duration)+.1) / 2) infinite normal none running svelte-vhcw6-short}@keyframes svelte-vhcw6-long{0%{left:-35%;right:100%}60%{left:100%;right:-90%}to{left:100%;right:-90%}}@keyframes svelte-vhcw6-short{0%{left:-200%;right:100%}60%{left:107%;right:-8%}to{left:107%;right:-8%}}.wrapper.svelte-1cy66mt{width:var(--size);height:var(--size)}.circle.svelte-1cy66mt{border-radius:100%;animation-fill-mode:both;position:absolute;opacity:0;width:var(--size);height:var(--size);background-color:var(--color);animation:svelte-1cy66mt-bounce var(--duration) linear infinite}@keyframes svelte-1cy66mt-bounce{0%{opacity:0;transform:scale(0)}5%{opacity:1}to{opacity:0;transform:scale(1)}}.wrapper.svelte-17ey38u{position:relative;width:var(--size);height:var(--size)}.border.svelte-17ey38u{border-color:var(--color);position:absolute;top:0px;left:0px;width:var(--size);height:var(--size);opacity:.4;perspective:800px;border-width:6px;border-style:solid;border-image:initial;border-radius:100%}.border.\31.svelte-17ey38u{animation:var(--duration) linear 0s infinite normal none running svelte-17ey38u-ringOne}.border.\32.svelte-17ey38u{animation:var(--duration) linear 0s infinite normal none running svelte-17ey38u-ringTwo}@keyframes svelte-17ey38u-ringOne{0%{transform:rotateX(0) rotateY(0) rotate(0)}to{transform:rotateX(360deg) rotateY(180deg) rotate(360deg)}}@keyframes svelte-17ey38u-ringTwo{0%{transform:rotateX(0) rotateY(0) rotate(0)}to{transform:rotateX(180deg) rotateY(360deg) rotate(360deg)}}.wrapper.svelte-14w6xk7{height:var(--size);width:var(--size);display:flex;align-items:center;justify-content:center}.dot.svelte-14w6xk7{height:var(--dotSize);width:var(--dotSize);background-color:var(--color);margin:2px;display:inline-block;border-radius:100%;animation:svelte-14w6xk7-sync var(--duration) ease-in-out infinite alternate both running}@-webkit-keyframes svelte-14w6xk7-sync{33%{-webkit-transform:translateY(10px);transform:translateY(10px)}66%{-webkit-transform:translateY(-10px);transform:translateY(-10px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes svelte-14w6xk7-sync{33%{-webkit-transform:translateY(10px);transform:translateY(10px)}66%{-webkit-transform:translateY(-10px);transform:translateY(-10px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.wrapper.svelte-1fuumrt{width:var(--size);height:calc(var(--size) / 2);overflow:hidden}.rainbow.svelte-1fuumrt{width:var(--size);height:var(--size);border-left-color:transparent;border-bottom-color:transparent;border-top-color:var(--color);border-right-color:var(--color);box-sizing:border-box;transform:rotate(-200deg);border-radius:50%;border-style:solid;animation:var(--duration) ease-in-out 0s infinite normal none running svelte-1fuumrt-rotate}@keyframes svelte-1fuumrt-rotate{0%{border-width:10px}25%{border-width:3px}50%{transform:rotate(115deg);border-width:10px}75%{border-width:3px}to{border-width:10px}}.wrapper.svelte-8cmcz4{position:relative;display:flex;justify-content:center;align-items:center;width:calc(var(--size) * 2.5);height:var(--size);overflow:hidden}.bar.svelte-8cmcz4{position:absolute;top:calc(var(--size) / 10);width:calc(var(--size) / 5);height:calc(var(--size) / 10);margin-top:calc(var(--size) - var(--size) / 10);transform:skewY(0);background-color:var(--color);animation:svelte-8cmcz4-motion var(--duration) ease-in-out infinite}@keyframes svelte-8cmcz4-motion{25%{transform:skewY(25deg)}50%{height:100%;margin-top:0}75%{transform:skewY(-25deg)}}.wrapper.svelte-1x2s7pr{width:calc(var(--size) * 1.3);height:calc(var(--size) * 1.3);display:flex;justify-content:center;align-items:center}.firework.svelte-1x2s7pr{border:calc(var(--size) / 10) dotted var(--color);width:var(--size);height:var(--size);border-radius:50%;animation:svelte-1x2s7pr-fire var(--duration) cubic-bezier(.165,.84,.44,1) infinite}@keyframes svelte-1x2s7pr-fire{0%{opacity:1;transform:scale(.1)}25%{opacity:.85}to{transform:scale(1);opacity:0}}.wrapper.svelte-446r86{position:relative;display:flex;justify-content:center;align-items:center;width:var(--size);height:calc(var(--size) / 2.5)}.cube.svelte-446r86{position:absolute;top:0px;width:calc(var(--size) / 5);height:calc(var(--size) / 2.5);background-color:var(--color);animation:svelte-446r86-motion var(--duration) cubic-bezier(.895,.03,.685,.22) infinite}@keyframes svelte-446r86-motion{0%{opacity:1}50%{opacity:0}to{opacity:1}}.wrapper.svelte-1v1mfqa{position:relative;display:flex;justify-content:center;align-items:center;width:var(--size);height:var(--size)}.ring.svelte-1v1mfqa{position:absolute;border:2px solid var(--color);border-radius:50%;background-color:transparent;animation:svelte-1v1mfqa-motion var(--duration) ease infinite}@keyframes svelte-1v1mfqa-motion{0%{transform:translateY(var(--motionOne))}50%{transform:translateY(var(--motionTwo))}to{transform:translateY(var(--motionThree))}}.wrapper.svelte-1unnvn6{height:var(--size);width:var(--size);display:flex;justify-content:center;align-items:center}.spinner.svelte-1unnvn6{height:var(--size);width:var(--size);animation:svelte-1unnvn6-rotate var(--duration) infinite linear}.dot.svelte-1unnvn6{width:60%;height:60%;display:inline-block;position:absolute;top:0;background-color:var(--color);border-radius:100%;animation:svelte-1unnvn6-bounce var(--duration) infinite ease-in-out}@keyframes svelte-1unnvn6-rotate{to{transform:rotate(360deg)}}@keyframes svelte-1unnvn6-bounce{0%,to{transform:scale(0)}50%{transform:scale(1)}}.wrapper.svelte-tycttu{position:relative;display:flex;justify-content:center;align-items:center;width:var(--size);height:var(--size)}.shadow.svelte-tycttu{color:var(--color);font-size:var(--size);overflow:hidden;width:var(--size);height:var(--size);border-radius:50%;margin:28px auto;position:relative;transform:translateZ(0);animation:svelte-tycttu-load var(--duration) infinite ease,svelte-tycttu-round var(--duration) infinite ease}@keyframes svelte-tycttu-load{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}to{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@keyframes svelte-tycttu-round{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.square.svelte-btmyrn{height:var(--size);width:var(--size);background-color:var(--color);animation:svelte-btmyrn-squareDelay var(--duration) 0s infinite cubic-bezier(.09,.57,.49,.9);animation-fill-mode:both;perspective:100px;display:inline-block}@keyframes svelte-btmyrn-squareDelay{25%{-webkit-transform:rotateX(180deg) rotateY(0);transform:rotateX(180deg) rotateY(0)}50%{-webkit-transform:rotateX(180deg) rotateY(180deg);transform:rotateX(180deg) rotateY(180deg)}75%{-webkit-transform:rotateX(0) rotateY(180deg);transform:rotateX(0) rotateY(180deg)}to{-webkit-transform:rotateX(0) rotateY(0);transform:rotateX(0) rotateY(0)}}.wrapper.svelte-nlgli4{height:var(--size);width:var(--size);border-radius:100%;animation:svelte-nlgli4-moonStretchDelay var(--duration) 0s infinite linear;animation-fill-mode:forwards;position:relative}.circle-one.svelte-nlgli4{top:var(--moonSize);background-color:var(--color);width:calc(var(--size) / 7);height:calc(var(--size) / 7);border-radius:100%;animation:svelte-nlgli4-moonStretchDelay var(--duration) 0s infinite linear;animation-fill-mode:forwards;opacity:.8;position:absolute}.circle-two.svelte-nlgli4{opacity:.1;border:calc(var(--size) / 7) solid var(--color);height:var(--size);width:var(--size);border-radius:100%;box-sizing:border-box}@keyframes svelte-nlgli4-moonStretchDelay{to{transform:rotate(360deg)}}.wrapper.svelte-1sqavxm.svelte-1sqavxm{height:var(--size);width:var(--size);position:relative;display:flex;justify-content:center;align-items:center}.wrapper.svelte-1sqavxm .svelte-1sqavxm{line-height:0;box-sizing:border-box}.spinner-inner.svelte-1sqavxm.svelte-1sqavxm{height:var(--size);width:var(--size);transform:scale(calc(var(--size) / 70))}.mask.svelte-1sqavxm.svelte-1sqavxm{position:absolute;border-radius:2px;overflow:hidden;perspective:1000;backface-visibility:hidden}.plane.svelte-1sqavxm.svelte-1sqavxm{background:var(--color);width:400%;height:100%;position:absolute;z-index:100;perspective:1000;backface-visibility:hidden}#top.svelte-1sqavxm .plane.svelte-1sqavxm{z-index:2000;animation:svelte-1sqavxm-trans1 var(--duration) ease-in infinite 0s backwards}#middle.svelte-1sqavxm .plane.svelte-1sqavxm{transform:translateZ(0);background:var(--rgba);animation:svelte-1sqavxm-trans2 var(--duration) linear infinite calc(var(--duration) / 4) backwards}#bottom.svelte-1sqavxm .plane.svelte-1sqavxm{z-index:2000;animation:svelte-1sqavxm-trans3 var(--duration) ease-out infinite calc(var(--duration) / 2) backwards}#top.svelte-1sqavxm.svelte-1sqavxm{width:53px;height:20px;left:20px;top:5px;transform:skew(-15deg);z-index:100}#middle.svelte-1sqavxm.svelte-1sqavxm{width:33px;height:20px;left:20px;top:21px;transform:skew(-15deg,40deg)}#bottom.svelte-1sqavxm.svelte-1sqavxm{width:53px;height:20px;top:35px;transform:skew(-15deg)}@keyframes svelte-1sqavxm-trans1{0%{transform:translate3d(53px,0,0)}to{transform:translate3d(-250px,0,0)}}@keyframes svelte-1sqavxm-trans2{0%{transform:translate3d(-160px,0,0)}to{transform:translate3d(53px,0,0)}}@keyframes svelte-1sqavxm-trans3{0%{transform:translate3d(53px,0,0)}to{transform:translate3d(-220px,0,0)}}span.svelte-evhfle{width:var(--size);height:calc(var(--size) / 4);position:relative;display:block}div.svelte-evhfle{width:calc(var(--size) / 4);height:calc(var(--size) / 4);position:absolute;left:0;top:0;border-radius:2px;background:var(--color);transform:translate(-50%) rotate(45deg) scale(0);animation:svelte-evhfle-diamonds var(--duration) linear infinite}div.svelte-evhfle:nth-child(1){animation-delay:calc(var(--duration) * 2 / 3 * -1)}div.svelte-evhfle:nth-child(2){animation-delay:calc(var(--duration) * 2 / 3 * -2)}div.svelte-evhfle:nth-child(3){animation-delay:calc(var(--duration) * 2 / 3 * -3)}@keyframes svelte-evhfle-diamonds{50%{left:50%;transform:translate(-50%) rotate(45deg) scale(1)}to{left:100%;transform:translate(-50%) rotate(45deg) scale(0)}}div.svelte-1cgj772{position:relative;width:var(--size);height:var(--size);background-color:transparent;box-shadow:inset 0 0 0 2px var(--color);border-radius:50%}div.svelte-1cgj772:before,div.svelte-1cgj772:after{position:absolute;content:"";background-color:var(--color)}div.svelte-1cgj772:after{width:calc(var(--size) / 2.4);height:2px;top:calc(var(--size) / 2);left:calc(var(--size) / 2);transform-origin:1px 1px;animation:svelte-1cgj772-rotate calc(var(--duration) / 4) linear infinite}div.svelte-1cgj772:before{width:calc(var(--size) / 3);height:2px;top:calc((var(--size) / 2));left:calc((var(--size) / 2));transform-origin:1px 1px;animation:svelte-1cgj772-rotate var(--duration) linear infinite}@keyframes svelte-1cgj772-rotate{to{transform:rotate(360deg)}}.panel.svelte-2b4oi9 a.svelte-2b4oi9{display:block;margin-left:auto;color:salmon;align-self:top}.panel.svelte-2b4oi9.svelte-2b4oi9{margin-bottom:1em;display:flex;width:100%;gap:.5em}.spinner-wrapper.svelte-ijikyg{position:absolute;top:0;left:0;height:100%;width:100%;display:grid;place-items:center}.divider.svelte-ijikyg{border-bottom:3px solid white}.output-container.svelte-ijikyg{--bc:black;white-space:pre-wrap;position:relative;padding:1em;background-color:#090909;font-family:Consolas,monospace;flex-basis:45%;border-left:4px solid var(--bc)}.output.svelte-ijikyg{color:#fff}.container.svelte-1xe614e{display:flex;flex-direction:column;min-height:100%;background-color:#fff}.editor-container.svelte-1xe614e{display:flex;flex-grow:1;position:relative}:root{--toastBackground:#322d3d;--toastColor:#dbdee1;--toastBorderRadius:5px;--toastBorder:2px solid rgb(109, 101, 127);--toastBarBackground:rgb(255, 101, 35);--toastMsgPadding:.4em .5em .8em .5em;--toastMinHeight:0;--toastWidth:auto} 2 | -------------------------------------------------------------------------------- /server/public/global.css: -------------------------------------------------------------------------------- 1 | /* Box sizing rules */ 2 | *, 3 | *::before, 4 | *::after { 5 | box-sizing: border-box; 6 | } 7 | 8 | /* Show focus ring only when navigated with keyboard */ 9 | button:focus:not(:focus-visible) { 10 | outline: none; 11 | } 12 | 13 | /* Remove default margin */ 14 | body, 15 | h1, 16 | h2, 17 | h3, 18 | h4, 19 | p, 20 | figure, 21 | blockquote, 22 | dl, 23 | dd, 24 | ul { 25 | margin: 0; 26 | } 27 | 28 | :root {} 29 | 30 | html { 31 | height: 100%; 32 | min-height: 100%; 33 | } 34 | 35 | body { 36 | text-rendering: optimizeSpeed; 37 | line-height: 1.25; 38 | height: 100%; 39 | min-height: 100%; 40 | transition: color 200ms, background-color 200ms; 41 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; 42 | } 43 | 44 | #app { 45 | height: 100%; 46 | min-height: 100%; 47 | } 48 | 49 | body, 50 | body * { 51 | overflow-wrap: break-word; 52 | min-width: 0; 53 | } 54 | 55 | /* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ 56 | ul, 57 | ol { 58 | list-style: none; 59 | padding: 0; 60 | } 61 | 62 | html:focus-within { 63 | scroll-behavior: smooth; 64 | } 65 | 66 | /* A elements that don't have a class get default styles */ 67 | a { 68 | text-decoration-skip-ink: auto; 69 | } 70 | 71 | /* Make images easier to work with */ 72 | img, 73 | picture, 74 | iframe { 75 | max-width: 100%; 76 | display: block; 77 | } 78 | 79 | /* Inherit fonts for inputs and buttons */ 80 | input, 81 | button, 82 | textarea, 83 | select { 84 | font: inherit; 85 | } 86 | 87 | /* Remove all animations and transitions for people that prefer not to see them */ 88 | @media (prefers-reduced-motion: reduce) { 89 | html:focus-within { 90 | scroll-behavior: auto; 91 | } 92 | 93 | *, 94 | *::before, 95 | *::after { 96 | animation-duration: 0.01ms !important; 97 | animation-iteration-count: 1 !important; 98 | transition-duration: 0.01ms !important; 99 | scroll-behavior: auto !important; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /server/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Typerust | Playground 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /server/src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | pub type Result = std::result::Result; 4 | 5 | #[derive(Error, Debug)] 6 | pub enum SandboxError { 7 | #[error("out of memory error")] 8 | OOM, 9 | #[error("internal error: {0}")] 10 | Internal(String), 11 | #[error("timeout error")] 12 | Timeout, 13 | } 14 | 15 | impl From for SandboxError { 16 | fn from(err: anyhow::Error) -> Self { 17 | let message = err.to_string(); 18 | err.downcast::() 19 | .unwrap_or(SandboxError::Internal(message)) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /server/src/handler.rs: -------------------------------------------------------------------------------- 1 | use crate::error::Result; 2 | use crate::wasm::execute_wasm; 3 | use crate::State; 4 | use anyhow::bail; 5 | use serde::Serialize; 6 | use std::path::PathBuf; 7 | use std::sync::Arc; 8 | use tempfile::TempDir; 9 | use tokio::fs; 10 | use tokio::process::Command; 11 | use tokio::time::{Duration, Instant}; 12 | use tracing::instrument; 13 | 14 | const CRATE_NAME: &str = "playground"; 15 | 16 | struct Compiler { 17 | #[allow(dead_code)] 18 | tempdir: TempDir, 19 | output_dir: PathBuf, 20 | input_file: PathBuf, 21 | } 22 | 23 | macro_rules! add_ext { 24 | ($filename:expr, $ext:expr) => { 25 | format!("{}.{}", $filename, $ext) 26 | }; 27 | } 28 | 29 | type OutputText = String; 30 | type ExecutablePath = PathBuf; 31 | 32 | #[derive(Debug)] 33 | enum BuildResult { 34 | Success { 35 | elapsed: Duration, 36 | executable: ExecutablePath, 37 | }, 38 | Failure(OutputText), 39 | } 40 | 41 | fn bytes_to_string(vec: Vec) -> anyhow::Result { 42 | let res = String::from_utf8(vec)?; 43 | Ok(res) 44 | } 45 | 46 | impl Compiler { 47 | async fn new() -> anyhow::Result { 48 | let tempdir = tempfile::Builder::new() 49 | .prefix("playground-") 50 | .rand_bytes(10) 51 | .tempdir(); 52 | 53 | if tempdir.is_err() { 54 | bail!("failed to create tempdir") 55 | } 56 | 57 | let tempdir = tempdir.unwrap(); 58 | 59 | let filename = add_ext!(CRATE_NAME, "rs"); 60 | let input_file = tempdir.path().join(filename); 61 | let output_dir = tempdir.path().join("out"); 62 | 63 | let create_dir_result = fs::create_dir(&output_dir).await; 64 | if create_dir_result.is_err() { 65 | bail!("failed to create output dir") 66 | } 67 | 68 | Ok(Self { 69 | tempdir, 70 | input_file, 71 | output_dir, 72 | }) 73 | } 74 | 75 | async fn write_source_code(&self, code: String) -> anyhow::Result<()> { 76 | let write_result = fs::write(&self.input_file, code).await; 77 | if write_result.is_err() { 78 | bail!("failed to write code to tempfile") 79 | } 80 | Ok(()) 81 | } 82 | 83 | async fn compile(&self, code: String) -> anyhow::Result { 84 | self.write_source_code(code).await?; 85 | 86 | let start = Instant::now(); 87 | let mut cmd = Command::new("rustc"); 88 | let cmd = cmd 89 | .arg("--out-dir") 90 | .arg(&self.output_dir) 91 | .arg("--target") 92 | .arg("wasm32-wasip1") 93 | .arg(&self.input_file); 94 | let output = cmd.output().await; 95 | 96 | if output.is_err() { 97 | bail!("failed to execute child command"); 98 | } 99 | 100 | let output = output.unwrap(); 101 | let elapsed = start.elapsed(); 102 | 103 | if !output.status.success() { 104 | let string = bytes_to_string(output.stderr); 105 | if string.is_err() { 106 | bail!("failed to parse command output as utf-8"); 107 | } 108 | let string = string.unwrap(); 109 | return Ok(BuildResult::Failure(string)); 110 | } 111 | 112 | let filename = add_ext!(CRATE_NAME, "wasm"); 113 | let executable = self.output_dir.join(filename); 114 | 115 | Ok(BuildResult::Success { 116 | executable, 117 | elapsed, 118 | }) 119 | } 120 | } 121 | 122 | #[derive(Serialize)] 123 | pub struct Success { 124 | elapsed: f32, 125 | output: Option, 126 | } 127 | 128 | #[derive(Serialize)] 129 | #[serde(tag = "type", content = "data")] 130 | pub enum HandlerResponse { 131 | Success(Success), 132 | Error(String), 133 | } 134 | 135 | #[instrument(skip_all, name = "Run playground code", fields( 136 | service.name = "typerust" 137 | ))] 138 | pub async fn run(code: String, state: Arc) -> Result { 139 | let compiler = Compiler::new().await?; 140 | let result = compiler.compile(code).await?; 141 | match result { 142 | BuildResult::Success { 143 | elapsed, 144 | executable, 145 | } => { 146 | tracing::info!("successfully compiled playground code"); 147 | let elapsed = elapsed.as_secs_f32(); 148 | let output = execute_wasm(state.engine.clone(), executable).await?; 149 | let success = Success { 150 | elapsed, 151 | output: Some(output), 152 | }; 153 | Ok(HandlerResponse::Success(success)) 154 | } 155 | BuildResult::Failure(output) => { 156 | tracing::error!("failed to build playground code"); 157 | Ok(HandlerResponse::Error(output)) 158 | } 159 | } 160 | } 161 | 162 | #[instrument(skip_all, name = "Build playground code", fields( 163 | service.name = "typerust" 164 | ))] 165 | pub async fn build(code: String) -> Result { 166 | let sandbox = Compiler::new().await?; 167 | let build_result = sandbox.compile(code).await?; 168 | match build_result { 169 | BuildResult::Success { elapsed, .. } => { 170 | tracing::info!("successfully compiled playground code"); 171 | let elapsed = elapsed.as_secs_f32(); 172 | let success = Success { 173 | elapsed, 174 | output: None, 175 | }; 176 | Ok(HandlerResponse::Success(success)) 177 | } 178 | BuildResult::Failure(output) => { 179 | tracing::error!("failed to build playground code"); 180 | Ok(HandlerResponse::Error(output)) 181 | } 182 | } 183 | } 184 | 185 | #[cfg(test)] 186 | mod tests { 187 | use super::*; 188 | use crate::{create_interruptable_engine, error::SandboxError}; 189 | use once_cell::sync::Lazy; 190 | 191 | static STATE: Lazy> = Lazy::new(|| { 192 | Arc::new(State { 193 | engine: create_interruptable_engine(), 194 | }) 195 | }); 196 | 197 | #[tokio::test] 198 | async fn kill_on_oom() -> anyhow::Result<()> { 199 | let sandbox = Compiler::new().await?; 200 | let code = r#" 201 | fn main() { 202 | let mut nums: Vec> = vec![]; 203 | for i in 0..100000000 { 204 | nums.push(Box::new(i)); 205 | } 206 | } 207 | "#; 208 | 209 | let result = sandbox.compile(code.into()).await?; 210 | 211 | assert!(matches!(result, BuildResult::Success { .. })); 212 | if let BuildResult::Success { executable, .. } = result { 213 | let result = execute_wasm(STATE.engine.clone(), executable).await.err(); 214 | let error = result.map(|err| err.downcast::()); 215 | assert!(matches!(error, Some(Ok(SandboxError::OOM)))); 216 | } 217 | 218 | Ok(()) 219 | } 220 | 221 | #[tokio::test] 222 | async fn stay_within_memory_limit() -> anyhow::Result<()> { 223 | let sandbox = Compiler::new().await?; 224 | let code = r#" 225 | fn main() { 226 | let mut nums: Vec> = vec![]; 227 | for i in 0..10 { 228 | nums.push(Box::new(i)); 229 | } 230 | } 231 | "#; 232 | 233 | let result = sandbox.compile(code.into()).await?; 234 | 235 | assert!(matches!(result, BuildResult::Success { .. })); 236 | 237 | if let BuildResult::Success { executable, .. } = result { 238 | let result = execute_wasm(STATE.engine.clone(), executable).await.err(); 239 | assert!(matches!(result, None)); 240 | } 241 | 242 | Ok(()) 243 | } 244 | 245 | #[tokio::test] 246 | async fn timeout_on_loop() -> anyhow::Result<()> { 247 | let sandbox = Compiler::new().await?; 248 | let code = r#" 249 | fn main() { 250 | loop {} 251 | } 252 | "#; 253 | 254 | let result = sandbox.compile(code.into()).await?; 255 | 256 | assert!(matches!(result, BuildResult::Success { .. })); 257 | 258 | if let BuildResult::Success { executable, .. } = result { 259 | let result = execute_wasm(STATE.engine.clone(), executable).await.err(); 260 | let error = result.map(|err| err.downcast::()); 261 | assert!(matches!(error, Some(Ok(SandboxError::Timeout)))); 262 | } 263 | 264 | Ok(()) 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /server/src/main.rs: -------------------------------------------------------------------------------- 1 | mod error; 2 | mod handler; 3 | mod static_server; 4 | mod telemetry; 5 | mod wasm; 6 | 7 | use crate::error::SandboxError; 8 | use axum::{ 9 | error_handling::HandleErrorLayer, 10 | http::{header, HeaderValue, Request, StatusCode}, 11 | middleware::{self, Next}, 12 | response::{IntoResponse, Response}, 13 | routing::post, 14 | Extension, Json, Router, 15 | }; 16 | use dotenv::dotenv; 17 | use handler::HandlerResponse; 18 | use serde::Deserialize; 19 | use std::net::SocketAddr; 20 | use std::{convert::Infallible, sync::Arc}; 21 | use tower_http::trace::{DefaultMakeSpan, DefaultOnRequest, DefaultOnResponse, TraceLayer}; 22 | use tracing::{instrument, subscriber::set_global_default, Level}; 23 | use wasm::create_interruptable_engine; 24 | 25 | const MAX_AGE_ONE_HOUR: HeaderValue = HeaderValue::from_static("public, max-age=3600"); 26 | const MAX_AGE_ONE_YEAR: HeaderValue = HeaderValue::from_static("public, max-age=31536000"); 27 | 28 | #[derive(Deserialize, Debug)] 29 | struct EnvConfig { 30 | ip_addr: SocketAddr, 31 | otlp_export_url: String, 32 | honeycomb_api_token: String, 33 | local_log_only: bool, 34 | } 35 | 36 | pub struct State { 37 | engine: wasmtime::Engine, 38 | } 39 | 40 | impl IntoResponse for SandboxError { 41 | fn into_response(self) -> Response { 42 | self.to_string().into_response() 43 | } 44 | } 45 | 46 | #[tokio::main] 47 | async fn main() { 48 | dotenv().ok(); 49 | 50 | let env = envy::from_env::().unwrap_or_else(|error| panic!("{:#?}", error)); 51 | 52 | if env.local_log_only { 53 | println!("installing stdout subscriber..."); 54 | let subscriber = telemetry::create_stdout_subscriber(); 55 | set_global_default(subscriber).expect("failed to set global subscriber"); 56 | } else { 57 | let subscriber = 58 | telemetry::create_otel_subscriber(env.honeycomb_api_token, env.otlp_export_url); 59 | set_global_default(subscriber).expect("failed to set global subscriber"); 60 | }; 61 | 62 | let engine = create_interruptable_engine(); 63 | let state = Arc::new(State { engine }); 64 | 65 | let static_service = static_server::file_service(MAX_AGE_ONE_HOUR, MAX_AGE_ONE_YEAR); 66 | 67 | let app = Router::new() 68 | .fallback(static_service) 69 | .route("/api/run", post(run)) 70 | .route("/api/build", post(build)) 71 | .layer( 72 | TraceLayer::new_for_http() 73 | .make_span_with(DefaultMakeSpan::new().level(Level::INFO)) 74 | .on_request(DefaultOnRequest::new().level(Level::INFO)) 75 | .on_response(DefaultOnResponse::new().level(Level::INFO)), 76 | ) 77 | .layer(Extension(state)) 78 | .layer(HandleErrorLayer::new(handle_error)) 79 | .layer(middleware::from_fn(uncache_404)); 80 | 81 | serve(app, env.ip_addr) 82 | .await 83 | .expect("server crashed unexpectedly"); 84 | } 85 | 86 | async fn uncache_404(req: Request, next: Next) -> impl IntoResponse { 87 | let mut res = next.run(req).await; 88 | if res.status() == StatusCode::NOT_FOUND { 89 | res.headers_mut() 90 | .remove(static_server::CDN_CACHE_CONTROL_HEADER); 91 | res.headers_mut().remove(header::CACHE_CONTROL); 92 | return (StatusCode::NOT_FOUND, "404 - nothing to see here").into_response(); 93 | } 94 | res 95 | } 96 | 97 | #[instrument(skip_all, name = "Invoke build handler", fields( 98 | service.name = "typerust" 99 | ))] 100 | async fn build(code: String) -> impl IntoResponse { 101 | let response = handler::build(code).await?; 102 | Ok::<_, SandboxError>(Json(response)) 103 | } 104 | 105 | #[instrument(skip_all, name = "Invoke run handler", fields( 106 | service.name = "typerust" 107 | ))] 108 | async fn run(code: String, Extension(state): Extension>) -> impl IntoResponse { 109 | match handler::run(code, state).await { 110 | Err(SandboxError::Internal(_)) => { 111 | tracing::error!("unexpected internal error"); 112 | Err(StatusCode::INTERNAL_SERVER_ERROR) 113 | } 114 | Err(SandboxError::Timeout) => { 115 | let response = HandlerResponse::Error( 116 | "RUNTIME ERROR: Your code took too long to execute and was interrupted".into(), 117 | ); 118 | Ok(Json(response)) 119 | } 120 | Err(_) => { 121 | tracing::error!("memory limit or unallowed filesystem/network access"); 122 | let response = HandlerResponse::Error( 123 | "RUNTIME ERROR: This could happen for the following reasons: 124 | a) you tried to access filesystem and/or network which is not allowed in this playground or 125 | b) your code exceeded memory limit and was interrupted." 126 | .into(), 127 | ); 128 | Ok(Json(response)) 129 | } 130 | Ok(resp) => Ok(Json(resp)), 131 | } 132 | } 133 | 134 | async fn handle_error(_: Infallible) -> (StatusCode, String) { 135 | ( 136 | StatusCode::INTERNAL_SERVER_ERROR, 137 | "internal server error".to_string(), 138 | ) 139 | } 140 | 141 | async fn serve(app: Router, addr: SocketAddr) -> Result<(), anyhow::Error> { 142 | println!("listening on {addr}..."); 143 | axum::Server::bind(&addr) 144 | .serve(app.into_make_service()) 145 | .await?; 146 | Ok(()) 147 | } 148 | -------------------------------------------------------------------------------- /server/src/static_server.rs: -------------------------------------------------------------------------------- 1 | use axum::body::{self, Full}; 2 | use axum::handler::Handler; 3 | use axum::http::header::HeaderName; 4 | use axum::http::{header, HeaderValue, Response, StatusCode, Uri}; 5 | use axum::response::IntoResponse; 6 | use axum::routing::{get, MethodRouter}; 7 | use bytes::Bytes; 8 | use http_body::combinators::UnsyncBoxBody; 9 | use include_dir::include_dir; 10 | use once_cell::sync::Lazy; 11 | use pulldown_cmark::{html, Parser}; 12 | use std::path::Path; 13 | use tera::{Context, Tera}; 14 | use tower_http::set_header::SetResponseHeaderLayer; 15 | 16 | pub const CDN_CACHE_CONTROL_HEADER: HeaderName = HeaderName::from_static("cdn-cache-control"); 17 | 18 | static STATIC_DIR: include_dir::Dir = include_dir!("public"); 19 | static TERA: Lazy = Lazy::new(|| match Tera::new("templates/**/*") { 20 | Ok(t) => t, 21 | Err(e) => { 22 | println!("Parsing error(s): {}", e); 23 | ::std::process::exit(1); 24 | } 25 | }); 26 | 27 | fn mime_type_from_path

(path: P) -> mime_guess::Mime 28 | where 29 | P: AsRef, 30 | { 31 | mime_guess::from_path(path).first_or_text_plain() 32 | } 33 | 34 | fn bytes_to_response( 35 | bytes: http_body::Full, 36 | mime_type: mime_guess::Mime, 37 | ) -> Response> { 38 | Response::builder() 39 | .header( 40 | header::CONTENT_TYPE, 41 | HeaderValue::from_str(mime_type.as_ref()).unwrap(), 42 | ) 43 | .status(StatusCode::OK) 44 | .body(body::boxed(bytes)) 45 | .unwrap() 46 | } 47 | 48 | fn file_to_response( 49 | file: &'static include_dir::File, 50 | ) -> Response> { 51 | bytes_to_response( 52 | Full::from(file.contents()), 53 | mime_type_from_path(file.path()), 54 | ) 55 | } 56 | 57 | fn convert_md_to_html(content: &str) -> Vec { 58 | let parser = Parser::new(content); 59 | let mut html_output = String::new(); 60 | html::push_html(&mut html_output, parser); 61 | 62 | let mut context = Context::new(); 63 | context.insert("html", &html_output); 64 | 65 | let mut buf = Vec::new(); 66 | TERA.render_to("base.html", &context, &mut buf).unwrap(); 67 | 68 | buf 69 | } 70 | 71 | async fn static_path(uri: Uri) -> impl IntoResponse { 72 | let path = uri.path().trim_start_matches('/'); 73 | let has_extension = path.split_once('.').is_some(); 74 | let not_found_response = StatusCode::NOT_FOUND.into_response(); 75 | 76 | if has_extension { 77 | let path = if path.is_empty() { "index.html" } else { path }; 78 | return STATIC_DIR 79 | .get_file(path) 80 | .map_or(not_found_response, file_to_response); 81 | } 82 | 83 | if path.is_empty() { 84 | return STATIC_DIR 85 | .get_file("index.html") 86 | .map_or(StatusCode::NOT_FOUND.into_response(), file_to_response); 87 | } 88 | 89 | let md = format!("{}.md", path); 90 | STATIC_DIR.get_file(md).map_or(not_found_response, |file| { 91 | let bytes = convert_md_to_html(file.contents_utf8().unwrap_or_default()); 92 | bytes_to_response(Full::from(bytes), mime_guess::mime::TEXT_HTML_UTF_8) 93 | }) 94 | } 95 | 96 | pub fn file_service(browser_max_age: HeaderValue, cdn_max_age: HeaderValue) -> MethodRouter { 97 | let static_handler = static_path 98 | .layer(SetResponseHeaderLayer::if_not_present( 99 | header::CACHE_CONTROL, 100 | browser_max_age, 101 | )) 102 | .layer(SetResponseHeaderLayer::if_not_present( 103 | CDN_CACHE_CONTROL_HEADER, 104 | cdn_max_age, 105 | )); 106 | get(static_handler) 107 | } 108 | -------------------------------------------------------------------------------- /server/src/telemetry.rs: -------------------------------------------------------------------------------- 1 | use opentelemetry::sdk::export::trace::stdout; 2 | use opentelemetry_otlp::WithExportConfig; 3 | use tonic::{metadata::MetadataMap, transport::ClientTlsConfig}; 4 | use tracing::Subscriber; 5 | use tracing_subscriber::layer::SubscriberExt; 6 | use tracing_subscriber::EnvFilter; 7 | use tracing_subscriber::Registry; 8 | use url::Url; 9 | 10 | pub fn create_stdout_subscriber() -> impl Subscriber { 11 | let filter_layer = EnvFilter::try_from_default_env() 12 | .or_else(|_| EnvFilter::try_new("info")) 13 | .unwrap(); 14 | 15 | let trace_config = 16 | opentelemetry::sdk::trace::config().with_resource(opentelemetry::sdk::Resource::new(vec![ 17 | opentelemetry::KeyValue::new("service.name", "typerust"), 18 | ])); 19 | 20 | let tracer = stdout::new_pipeline() 21 | .with_trace_config(trace_config) 22 | .with_pretty_print(true) 23 | .install_simple(); 24 | let telemetry = tracing_opentelemetry::layer().with_tracer(tracer); 25 | 26 | tracing_subscriber::registry() 27 | .with(filter_layer) 28 | .with(telemetry) 29 | } 30 | 31 | pub fn create_otel_subscriber( 32 | honeycomb_api_token: String, 33 | otlp_export_url: String, 34 | ) -> impl Subscriber { 35 | let filter = EnvFilter::try_from_default_env() 36 | .or_else(|_| EnvFilter::try_new("info")) 37 | .unwrap(); 38 | 39 | let mut metadata = MetadataMap::with_capacity(3); 40 | metadata.insert("x-honeycomb-team", honeycomb_api_token.parse().unwrap()); 41 | 42 | let endpoint = Url::parse(&otlp_export_url).expect("endpoint is not a valid url"); 43 | let otlp_exporter = opentelemetry_otlp::new_exporter() 44 | .tonic() 45 | .with_metadata(metadata) 46 | .with_endpoint(endpoint.as_str()) 47 | .with_tls_config( 48 | ClientTlsConfig::new().domain_name( 49 | endpoint 50 | .host_str() 51 | .expect("the specified endpoint should have a valid host"), 52 | ), 53 | ); 54 | 55 | let trace_config = 56 | opentelemetry::sdk::trace::config().with_resource(opentelemetry::sdk::Resource::new(vec![ 57 | opentelemetry::KeyValue::new("service.name", "typerust"), 58 | ])); 59 | 60 | let tracer = opentelemetry_otlp::new_pipeline() 61 | .tracing() 62 | .with_trace_config(trace_config) 63 | .with_exporter(otlp_exporter) 64 | .install_batch(opentelemetry::runtime::Tokio) 65 | .expect("failed to create otel pipeline"); 66 | 67 | let telemetry = tracing_opentelemetry::layer().with_tracer(tracer); 68 | 69 | // Use the tracing subscriber `Registry`, or any other subscriber 70 | // that impls `LookupSpan` 71 | Registry::default().with(telemetry).with(filter) 72 | } 73 | -------------------------------------------------------------------------------- /server/src/wasm.rs: -------------------------------------------------------------------------------- 1 | use std::io::Read; 2 | use std::io::Seek; 3 | use std::path::Path; 4 | 5 | use crate::error::SandboxError; 6 | use anyhow::bail; 7 | use tokio::time::{interval, Duration}; 8 | use tracing::instrument; 9 | use tracing::Instrument; 10 | use wasmtime::Config; 11 | use wasmtime::Trap; 12 | use wasmtime::{Engine, Linker, Module, ResourceLimiter, Store, StoreLimits, StoreLimitsBuilder}; 13 | use wasmtime_wasi::preview1::WasiP1Ctx; 14 | 15 | const WASM_MINIMUM_MEMORY_SIZE: u64 = bytesize::KIB * 64 * 17; 16 | const WASM_INSTANCE_MEMORY_LIMIT: u64 = WASM_MINIMUM_MEMORY_SIZE + bytesize::MB * 100; 17 | const TICKS_BEFORE_TIMEOUT: u64 = 5; 18 | 19 | struct WasmStoreData { 20 | wasi: WasiP1Ctx, 21 | memory_limiter: MemoryLimiter, 22 | } 23 | 24 | struct MemoryLimiter { 25 | limiter: StoreLimits, 26 | memory_limit_exceeded: bool, 27 | } 28 | 29 | impl MemoryLimiter { 30 | fn new(limiter: StoreLimits) -> Self { 31 | Self { 32 | limiter, 33 | memory_limit_exceeded: false, 34 | } 35 | } 36 | 37 | fn memory_limit_exceeded(&self) -> bool { 38 | self.memory_limit_exceeded 39 | } 40 | } 41 | 42 | impl ResourceLimiter for MemoryLimiter { 43 | fn memory_growing( 44 | &mut self, 45 | _current: usize, 46 | desired: usize, 47 | _maximum: Option, 48 | ) -> anyhow::Result { 49 | let is_rejected = self.limiter.memory_growing(_current, desired, _maximum); 50 | if let Ok(is_rejected) = is_rejected { 51 | if is_rejected { 52 | self.memory_limit_exceeded = true; 53 | } 54 | } 55 | is_rejected 56 | } 57 | 58 | fn table_growing( 59 | &mut self, 60 | current: usize, 61 | desired: usize, 62 | maximum: Option, 63 | ) -> anyhow::Result { 64 | self.limiter.table_growing(current, desired, maximum) 65 | } 66 | 67 | fn table_grow_failed(&mut self, _error: anyhow::Error) -> anyhow::Result<()> { 68 | Err(anyhow::format_err!("table_grow_failed")) 69 | } 70 | 71 | fn memory_grow_failed(&mut self, _error: anyhow::Error) -> anyhow::Result<()> { 72 | self.memory_limit_exceeded = true; 73 | Err(anyhow::format_err!("memory_grow_failed")) 74 | } 75 | } 76 | 77 | fn is_deadline_error(err: &Trap) -> bool { 78 | err.to_string().starts_with("epoch deadline") 79 | } 80 | 81 | fn run_wasm_instance( 82 | module: &Module, 83 | engine: &Engine, 84 | mut store: &mut Store, 85 | ) -> anyhow::Result> { 86 | use wasmtime_wasi::preview1; 87 | 88 | let mut linker: Linker = Linker::new(&engine); 89 | preview1::add_to_linker_sync(&mut linker, |t| &mut t.wasi)?; 90 | let pre = linker.instantiate_pre(&module)?; 91 | let instance = pre.instantiate(&mut store)?; 92 | 93 | let err = instance 94 | .get_typed_func::<(), ()>(&mut store, "_start")? 95 | .call(&mut store, ()) 96 | .err(); 97 | 98 | Ok(err) 99 | } 100 | 101 | fn run_wasm_timeout(engine: Engine) -> tokio::task::JoinHandle<()> { 102 | tokio::task::spawn(async move { 103 | let mut interval = interval(Duration::from_millis(1000)); 104 | for _ in 0..TICKS_BEFORE_TIMEOUT { 105 | interval.tick().await; 106 | engine.increment_epoch(); 107 | } 108 | }) 109 | } 110 | 111 | use std::fs::File; 112 | 113 | #[cfg(target_os = "linux")] 114 | fn create_stdout_file() -> std::io::Result { 115 | use tempfile::tempfile; 116 | tempfile() 117 | } 118 | 119 | #[cfg(target_os = "macos")] 120 | fn create_stdout_file() -> std::io::Result { 121 | use tempfile::tempfile; 122 | tempfile() 123 | } 124 | 125 | fn execute_wasm_instance(module: Module, engine: Engine) -> anyhow::Result { 126 | use wasmtime_wasi::WasiCtxBuilder; 127 | 128 | let mut memfile = create_stdout_file()?; 129 | let stdout_file = wasmtime_wasi::OutputFile::new(memfile.try_clone()?); 130 | let wasi = WasiCtxBuilder::new().stdout(stdout_file).build_p1(); 131 | 132 | let mut store = create_wasm_store(&engine, wasi); 133 | store.set_epoch_deadline(TICKS_BEFORE_TIMEOUT); 134 | 135 | let timeout = run_wasm_timeout(engine.clone()); 136 | let err = run_wasm_instance(&module, &engine, &mut store)?; 137 | 138 | if let Some(err) = err { 139 | if is_deadline_error(&err.downcast::()?) { 140 | tracing::info!("SandboxError::Timeout"); 141 | bail!(SandboxError::Timeout) 142 | } 143 | 144 | if store.data().memory_limiter.memory_limit_exceeded() { 145 | timeout.abort(); 146 | tracing::info!("SandboxError::OOM"); 147 | bail!(SandboxError::OOM) 148 | } 149 | } 150 | 151 | timeout.abort(); 152 | if let Err(e) = memfile.rewind() { 153 | bail!("failed to rewind: {e}") 154 | } 155 | 156 | let mut output = String::new(); 157 | memfile.read_to_string(&mut output)?; 158 | 159 | Ok(output) 160 | } 161 | 162 | fn create_wasm_store(engine: &Engine, wasi: WasiP1Ctx) -> Store { 163 | let store_limits = StoreLimitsBuilder::new() 164 | .memory_size(WASM_INSTANCE_MEMORY_LIMIT as usize) 165 | .build(); 166 | let memory_limiter = MemoryLimiter::new(store_limits); 167 | let mut store = Store::new( 168 | engine, 169 | WasmStoreData { 170 | wasi, 171 | memory_limiter, 172 | }, 173 | ); 174 | store.limiter(|data| &mut data.memory_limiter); 175 | store 176 | } 177 | 178 | #[instrument(skip_all, name = "Executing WASM instance", fields( 179 | service.name = "typerust" 180 | ))] 181 | pub async fn execute_wasm(engine: Engine, module_path: impl AsRef) -> anyhow::Result { 182 | let module = Module::from_file(&engine, module_path)?; 183 | let task_span = tracing::info_span!("Running execution task"); 184 | tokio::task::spawn_blocking(move || execute_wasm_instance(module, engine)) 185 | .instrument(task_span) 186 | .await? 187 | } 188 | 189 | pub fn create_interruptable_engine() -> Engine { 190 | let mut engine_config = Config::new(); 191 | engine_config.epoch_interruption(true); 192 | Engine::new(&engine_config).expect("failed to initialize wasm engine") 193 | } 194 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | About 7 | 8 | 9 | 10 | 11 | 12 | 54 | 55 | 56 | 57 |

58 | {{ html | safe }} 59 |
60 | 61 | 62 | 63 | --------------------------------------------------------------------------------