├── .cargo └── config.toml ├── .env.example ├── .github └── workflows │ └── clippy.yml ├── .gitignore ├── .gitpod.yml ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── Procfile ├── README.md ├── app.json ├── docker-compose.yml ├── gitpod.Dockerfile ├── marketplace ├── .gitignore ├── README.md ├── index.html ├── nodemon.json ├── package.json ├── pnpm-lock.yaml ├── public │ ├── GitHub-Mark-Light-64px.png │ ├── lapce-30px.png │ ├── lapce-35px.png │ └── lapce.png ├── src │ ├── App.svelte │ ├── app.css │ ├── components │ │ ├── NavBar.svelte │ │ ├── Sticky.svelte │ │ └── UserIndicator.svelte │ ├── main.ts │ └── vite-env.d.ts ├── svelte.config.js ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts ├── package.json ├── prisma ├── migrations │ ├── 20221009190213_user │ │ └── migration.sql │ ├── 20221009192036_change_id_int_to_bigint │ │ └── migration.sql │ └── migration_lock.toml └── schema.prisma ├── prisma_cli ├── Cargo.toml └── src │ └── main.rs ├── rust-toolchain ├── scripts ├── build-frontend.sh └── start.sh └── src ├── db.rs ├── db └── prisma.rs ├── error.rs ├── github.rs ├── main.rs └── user.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | prisma = "run -r -p prisma_cli --" 3 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgres://postgres:devpasswd@localhost:54320/passwdmanager 2 | REDIS_URL=redis://localhost 3 | # I plan to add more ways to store the plugins, 4 | # so i don't depend on the filesystem 5 | STORAGE=filesystem 6 | GH_CLIENT_ID=... 7 | GH_CLIENT_SECRET=... 8 | GH_REDIRECT_URL=... -------------------------------------------------------------------------------- /.github/workflows/clippy.yml: -------------------------------------------------------------------------------- 1 | name: Clippy 2 | 3 | on: [ pull_request ] 4 | 5 | env: 6 | CARGO_TERM_COLOR: always 7 | 8 | jobs: 9 | run-clippy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Clippy 14 | run: rustup component add clippy-preview && cargo clippy --verbose 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Rocket.toml 2 | /target 3 | /marketplace/dist 4 | # This directory is created by the filesystem implementation of storage 5 | /fs-registry 6 | .env 7 | /.idea/ 8 | 9 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - name: Backend 3 | init: | 4 | cargo build -p server 5 | command: | 6 | export GP_URL=$(gp url) 7 | export GH_REDIRECT_URL="${GP_URL:0:8}8000-${GP_URL:8}/auth/github" 8 | export ROCKET_PORT=8000 9 | make 10 | - name: Build frontend 11 | init: | 12 | cd marketplace && pnpm install 13 | command: cd /workspace/*/marketplace && nodemon 14 | image: 15 | file: gitpod.Dockerfile 16 | ports: 17 | - port: 6379 18 | onOpen: ignore 19 | - port: 54320 20 | onOpen: ignore 21 | vscode: 22 | extensions: 23 | - https://github.com/rust-lang/rust-analyzer/releases/latest/download/rust-analyzer-linux-x64.vsix 24 | - serayuzgur.crates 25 | - bungcip.better-toml 26 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "server" 3 | version = "0.1.0" 4 | edition = "2021" 5 | default-run = "server" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | rocket = { version = "0.5.0-rc.2", features = ["tls", "json", "serde_json", "secrets"] } 11 | rocket_oauth2 = "0.5.0-rc.1" 12 | octorust = "0.1.37" 13 | dotenvy = "0.15.3" 14 | rocket-session-store = { version = "0.2.0", features = ["redis"] } 15 | redis = "0.21.6" 16 | reqwest = { version = "0.11.11", features = ["json"] } 17 | toml = "0.5.9" 18 | prisma-client-rust = { git = "https://github.com/Brendonovich/prisma-client-rust", tag = "0.6.1" } 19 | [dependencies.serde] 20 | version = "1.0.144" 21 | features = ["derive"] 22 | 23 | [workspace] 24 | resolver = "2" 25 | members = ["prisma_cli"] 26 | default-members=["prisma_cli", "."] 27 | [profile.release] 28 | lto = "off" 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: dev_server 2 | dev_server: 3 | scripts/start.sh 4 | client: 5 | scripts/build-frontend.sh -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: ROCKET_ADDRESS=0.0.0.0 ROCKET_PORT=$PORT ROCKET_KEEP_ALIVE=0 ./target/release/server 2 | release: target/release/prisma_cli db push 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lapce Registry 2 | ![Heroku deploy](https://img.shields.io/github/deployments/lapce/lapce-extensions/lapce-extensions?color=%236762A6&label=heroku%20deploy) 3 | 4 | This is the software running the [lapce plugin registry](https://registry.lapce.dev), this manages and hosts plugins that the community uploads. 5 | 6 | ## Run the registry locally 7 | ### Requirements: 8 | - Docker Compose (to run the databases) 9 | - Rust Nightly or [rustup](https://rustup.rs) 10 | - Node.js 11 | - Nodemon: `npm install -g nodemon` 12 | ### Running 13 | 1. First create a .env from .env.example: `cp .env.example .env` 14 | 2. Create a GitHub OAuth app (always configure the redirect URL to `http://localhost:8000/auth/github`) 15 | 3. Configure the GitHub Single Sign-On: 16 | ``` 17 | GH_CLIENT_ID= 18 | GH_CLIENT_SECRET= 19 | GH_REDIRECT_URL=http://localhost:8000/auth/github 20 | ``` 21 | 4. `npm install` to install the JS dependencies 22 | 5. `make client` to build the frontend and watch for changes 23 | 6. Run `make` on a separate terminal to build 24 | and run the backend and watch for changes 25 | 26 | And now you've got a dev environment :tada:! 27 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Lapce Registry", 3 | "description": "Lapce's plugin registry", 4 | "repository": "https://github.com/lapce/lapce-extensions", 5 | "success_url": "/", 6 | "formation": { 7 | "web": { 8 | "quantity": 1, 9 | "size": "free" 10 | } 11 | }, 12 | "addons": ["heroku-postgresql:hobby-dev", "heroku-redis:hobby-dev"], 13 | "environments": { 14 | "review": { 15 | "addons": ["heroku-postgresql:hobby-dev", "heroku-redis:hobby-dev"] 16 | } 17 | }, 18 | "buildpacks": [ 19 | { "url": "heroku/nodejs" }, 20 | { "url": "emk/rust" } 21 | ] 22 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | 3 | services: 4 | postgres_dev: 5 | container_name: 'postgres-dev' 6 | image: postgres 7 | 8 | env_file: 9 | - .env 10 | environment: 11 | POSTGRES_PASSWORD: devpasswd 12 | POSTGRES_DB: passwdmanager 13 | POSTGRES_HOST: localhost 14 | POSTGRES_PORT: 54320 15 | ports: 16 | - '54320:5432' 17 | volumes: 18 | - postgres_data:/data/postgres 19 | restart: unless-stopped 20 | redis: 21 | container_name: 'redis-dev' 22 | image: redis 23 | ports: 24 | - "6379:6379" 25 | volumes: 26 | postgres_data: 27 | -------------------------------------------------------------------------------- /gitpod.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full 2 | RUN npm install --global nodemon 3 | RUN cargo install diesel_cli --no-default-features -F postgres 4 | -------------------------------------------------------------------------------- /marketplace/.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 | -------------------------------------------------------------------------------- /marketplace/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 | -------------------------------------------------------------------------------- /marketplace/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Lapce Marketplace 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /marketplace/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": [ 3 | "node_modules", 4 | "public", 5 | "src", 6 | "index.html", 7 | "svelte.config.js", 8 | "tsconfig.json", 9 | "tsconfig.node.json", 10 | "vite.config.ts" 11 | ], 12 | "ext": "*", 13 | "exec": "node_modules/.bin/vite build" 14 | } -------------------------------------------------------------------------------- /marketplace/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "marketplace", 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 | "dependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^1.0.2", 14 | "@tsconfig/svelte": "^3.0.0", 15 | "svelte": "^3.49.0", 16 | "svelte-check": "^2.8.1", 17 | "svelte-preprocess": "^4.10.7", 18 | "tslib": "^2.4.0", 19 | "typescript": "^4.6.4", 20 | "vite": "^3.1.0", 21 | "cookie": "^0.5.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /marketplace/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | '@sveltejs/vite-plugin-svelte': ^1.0.2 5 | '@tsconfig/svelte': ^3.0.0 6 | cookie: ^0.5.0 7 | svelte: ^3.49.0 8 | svelte-check: ^2.8.1 9 | svelte-preprocess: ^4.10.7 10 | tslib: ^2.4.0 11 | typescript: ^4.6.4 12 | vite: ^3.1.0 13 | 14 | dependencies: 15 | cookie: 0.5.0 16 | 17 | devDependencies: 18 | '@sveltejs/vite-plugin-svelte': 1.0.5_svelte@3.50.1+vite@3.1.0 19 | '@tsconfig/svelte': 3.0.0 20 | svelte: 3.50.1 21 | svelte-check: 2.9.0_svelte@3.50.1 22 | svelte-preprocess: 4.10.7_iprco5tylfmvffqgrvqxc46njy 23 | tslib: 2.4.0 24 | typescript: 4.8.3 25 | vite: 3.1.0 26 | 27 | packages: 28 | 29 | /@esbuild/linux-loong64/0.15.7: 30 | resolution: {integrity: sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==} 31 | engines: {node: '>=12'} 32 | cpu: [loong64] 33 | os: [linux] 34 | requiresBuild: true 35 | dev: true 36 | optional: true 37 | 38 | /@jridgewell/resolve-uri/3.1.0: 39 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} 40 | engines: {node: '>=6.0.0'} 41 | dev: true 42 | 43 | /@jridgewell/sourcemap-codec/1.4.14: 44 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} 45 | dev: true 46 | 47 | /@jridgewell/trace-mapping/0.3.15: 48 | resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==} 49 | dependencies: 50 | '@jridgewell/resolve-uri': 3.1.0 51 | '@jridgewell/sourcemap-codec': 1.4.14 52 | dev: true 53 | 54 | /@nodelib/fs.scandir/2.1.5: 55 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 56 | engines: {node: '>= 8'} 57 | dependencies: 58 | '@nodelib/fs.stat': 2.0.5 59 | run-parallel: 1.2.0 60 | dev: true 61 | 62 | /@nodelib/fs.stat/2.0.5: 63 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 64 | engines: {node: '>= 8'} 65 | dev: true 66 | 67 | /@nodelib/fs.walk/1.2.8: 68 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 69 | engines: {node: '>= 8'} 70 | dependencies: 71 | '@nodelib/fs.scandir': 2.1.5 72 | fastq: 1.13.0 73 | dev: true 74 | 75 | /@rollup/pluginutils/4.2.1: 76 | resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} 77 | engines: {node: '>= 8.0.0'} 78 | dependencies: 79 | estree-walker: 2.0.2 80 | picomatch: 2.3.1 81 | dev: true 82 | 83 | /@sveltejs/vite-plugin-svelte/1.0.5_svelte@3.50.1+vite@3.1.0: 84 | resolution: {integrity: sha512-CmSdSow0Dr5ua1A11BQMtreWnE0JZmkVIcRU/yG3PKbycKUpXjNdgYTWFSbStLB0vdlGnBbm2+Y4sBVj+C+TIw==} 85 | engines: {node: ^14.18.0 || >= 16} 86 | peerDependencies: 87 | diff-match-patch: ^1.0.5 88 | svelte: ^3.44.0 89 | vite: ^3.0.0 90 | peerDependenciesMeta: 91 | diff-match-patch: 92 | optional: true 93 | dependencies: 94 | '@rollup/pluginutils': 4.2.1 95 | debug: 4.3.4 96 | deepmerge: 4.2.2 97 | kleur: 4.1.5 98 | magic-string: 0.26.3 99 | svelte: 3.50.1 100 | svelte-hmr: 0.14.12_svelte@3.50.1 101 | vite: 3.1.0 102 | transitivePeerDependencies: 103 | - supports-color 104 | dev: true 105 | 106 | /@tsconfig/svelte/3.0.0: 107 | resolution: {integrity: sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==} 108 | dev: true 109 | 110 | /@types/node/18.7.18: 111 | resolution: {integrity: sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg==} 112 | dev: true 113 | 114 | /@types/pug/2.0.6: 115 | resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} 116 | dev: true 117 | 118 | /@types/sass/1.43.1: 119 | resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} 120 | dependencies: 121 | '@types/node': 18.7.18 122 | dev: true 123 | 124 | /anymatch/3.1.2: 125 | resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} 126 | engines: {node: '>= 8'} 127 | dependencies: 128 | normalize-path: 3.0.0 129 | picomatch: 2.3.1 130 | dev: true 131 | 132 | /balanced-match/1.0.2: 133 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 134 | dev: true 135 | 136 | /binary-extensions/2.2.0: 137 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 138 | engines: {node: '>=8'} 139 | dev: true 140 | 141 | /brace-expansion/1.1.11: 142 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 143 | dependencies: 144 | balanced-match: 1.0.2 145 | concat-map: 0.0.1 146 | dev: true 147 | 148 | /braces/3.0.2: 149 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 150 | engines: {node: '>=8'} 151 | dependencies: 152 | fill-range: 7.0.1 153 | dev: true 154 | 155 | /buffer-crc32/0.2.13: 156 | resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} 157 | dev: true 158 | 159 | /callsites/3.1.0: 160 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 161 | engines: {node: '>=6'} 162 | dev: true 163 | 164 | /chokidar/3.5.3: 165 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 166 | engines: {node: '>= 8.10.0'} 167 | dependencies: 168 | anymatch: 3.1.2 169 | braces: 3.0.2 170 | glob-parent: 5.1.2 171 | is-binary-path: 2.1.0 172 | is-glob: 4.0.3 173 | normalize-path: 3.0.0 174 | readdirp: 3.6.0 175 | optionalDependencies: 176 | fsevents: 2.3.2 177 | dev: true 178 | 179 | /concat-map/0.0.1: 180 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 181 | dev: true 182 | 183 | /cookie/0.5.0: 184 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} 185 | engines: {node: '>= 0.6'} 186 | dev: false 187 | 188 | /debug/4.3.4: 189 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 190 | engines: {node: '>=6.0'} 191 | peerDependencies: 192 | supports-color: '*' 193 | peerDependenciesMeta: 194 | supports-color: 195 | optional: true 196 | dependencies: 197 | ms: 2.1.2 198 | dev: true 199 | 200 | /deepmerge/4.2.2: 201 | resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} 202 | engines: {node: '>=0.10.0'} 203 | dev: true 204 | 205 | /detect-indent/6.1.0: 206 | resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} 207 | engines: {node: '>=8'} 208 | dev: true 209 | 210 | /es6-promise/3.3.1: 211 | resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} 212 | dev: true 213 | 214 | /esbuild-android-64/0.15.7: 215 | resolution: {integrity: sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==} 216 | engines: {node: '>=12'} 217 | cpu: [x64] 218 | os: [android] 219 | requiresBuild: true 220 | dev: true 221 | optional: true 222 | 223 | /esbuild-android-arm64/0.15.7: 224 | resolution: {integrity: sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==} 225 | engines: {node: '>=12'} 226 | cpu: [arm64] 227 | os: [android] 228 | requiresBuild: true 229 | dev: true 230 | optional: true 231 | 232 | /esbuild-darwin-64/0.15.7: 233 | resolution: {integrity: sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==} 234 | engines: {node: '>=12'} 235 | cpu: [x64] 236 | os: [darwin] 237 | requiresBuild: true 238 | dev: true 239 | optional: true 240 | 241 | /esbuild-darwin-arm64/0.15.7: 242 | resolution: {integrity: sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==} 243 | engines: {node: '>=12'} 244 | cpu: [arm64] 245 | os: [darwin] 246 | requiresBuild: true 247 | dev: true 248 | optional: true 249 | 250 | /esbuild-freebsd-64/0.15.7: 251 | resolution: {integrity: sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==} 252 | engines: {node: '>=12'} 253 | cpu: [x64] 254 | os: [freebsd] 255 | requiresBuild: true 256 | dev: true 257 | optional: true 258 | 259 | /esbuild-freebsd-arm64/0.15.7: 260 | resolution: {integrity: sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==} 261 | engines: {node: '>=12'} 262 | cpu: [arm64] 263 | os: [freebsd] 264 | requiresBuild: true 265 | dev: true 266 | optional: true 267 | 268 | /esbuild-linux-32/0.15.7: 269 | resolution: {integrity: sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==} 270 | engines: {node: '>=12'} 271 | cpu: [ia32] 272 | os: [linux] 273 | requiresBuild: true 274 | dev: true 275 | optional: true 276 | 277 | /esbuild-linux-64/0.15.7: 278 | resolution: {integrity: sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==} 279 | engines: {node: '>=12'} 280 | cpu: [x64] 281 | os: [linux] 282 | requiresBuild: true 283 | dev: true 284 | optional: true 285 | 286 | /esbuild-linux-arm/0.15.7: 287 | resolution: {integrity: sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==} 288 | engines: {node: '>=12'} 289 | cpu: [arm] 290 | os: [linux] 291 | requiresBuild: true 292 | dev: true 293 | optional: true 294 | 295 | /esbuild-linux-arm64/0.15.7: 296 | resolution: {integrity: sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==} 297 | engines: {node: '>=12'} 298 | cpu: [arm64] 299 | os: [linux] 300 | requiresBuild: true 301 | dev: true 302 | optional: true 303 | 304 | /esbuild-linux-mips64le/0.15.7: 305 | resolution: {integrity: sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==} 306 | engines: {node: '>=12'} 307 | cpu: [mips64el] 308 | os: [linux] 309 | requiresBuild: true 310 | dev: true 311 | optional: true 312 | 313 | /esbuild-linux-ppc64le/0.15.7: 314 | resolution: {integrity: sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==} 315 | engines: {node: '>=12'} 316 | cpu: [ppc64] 317 | os: [linux] 318 | requiresBuild: true 319 | dev: true 320 | optional: true 321 | 322 | /esbuild-linux-riscv64/0.15.7: 323 | resolution: {integrity: sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==} 324 | engines: {node: '>=12'} 325 | cpu: [riscv64] 326 | os: [linux] 327 | requiresBuild: true 328 | dev: true 329 | optional: true 330 | 331 | /esbuild-linux-s390x/0.15.7: 332 | resolution: {integrity: sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==} 333 | engines: {node: '>=12'} 334 | cpu: [s390x] 335 | os: [linux] 336 | requiresBuild: true 337 | dev: true 338 | optional: true 339 | 340 | /esbuild-netbsd-64/0.15.7: 341 | resolution: {integrity: sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==} 342 | engines: {node: '>=12'} 343 | cpu: [x64] 344 | os: [netbsd] 345 | requiresBuild: true 346 | dev: true 347 | optional: true 348 | 349 | /esbuild-openbsd-64/0.15.7: 350 | resolution: {integrity: sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==} 351 | engines: {node: '>=12'} 352 | cpu: [x64] 353 | os: [openbsd] 354 | requiresBuild: true 355 | dev: true 356 | optional: true 357 | 358 | /esbuild-sunos-64/0.15.7: 359 | resolution: {integrity: sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==} 360 | engines: {node: '>=12'} 361 | cpu: [x64] 362 | os: [sunos] 363 | requiresBuild: true 364 | dev: true 365 | optional: true 366 | 367 | /esbuild-windows-32/0.15.7: 368 | resolution: {integrity: sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==} 369 | engines: {node: '>=12'} 370 | cpu: [ia32] 371 | os: [win32] 372 | requiresBuild: true 373 | dev: true 374 | optional: true 375 | 376 | /esbuild-windows-64/0.15.7: 377 | resolution: {integrity: sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==} 378 | engines: {node: '>=12'} 379 | cpu: [x64] 380 | os: [win32] 381 | requiresBuild: true 382 | dev: true 383 | optional: true 384 | 385 | /esbuild-windows-arm64/0.15.7: 386 | resolution: {integrity: sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==} 387 | engines: {node: '>=12'} 388 | cpu: [arm64] 389 | os: [win32] 390 | requiresBuild: true 391 | dev: true 392 | optional: true 393 | 394 | /esbuild/0.15.7: 395 | resolution: {integrity: sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==} 396 | engines: {node: '>=12'} 397 | hasBin: true 398 | requiresBuild: true 399 | optionalDependencies: 400 | '@esbuild/linux-loong64': 0.15.7 401 | esbuild-android-64: 0.15.7 402 | esbuild-android-arm64: 0.15.7 403 | esbuild-darwin-64: 0.15.7 404 | esbuild-darwin-arm64: 0.15.7 405 | esbuild-freebsd-64: 0.15.7 406 | esbuild-freebsd-arm64: 0.15.7 407 | esbuild-linux-32: 0.15.7 408 | esbuild-linux-64: 0.15.7 409 | esbuild-linux-arm: 0.15.7 410 | esbuild-linux-arm64: 0.15.7 411 | esbuild-linux-mips64le: 0.15.7 412 | esbuild-linux-ppc64le: 0.15.7 413 | esbuild-linux-riscv64: 0.15.7 414 | esbuild-linux-s390x: 0.15.7 415 | esbuild-netbsd-64: 0.15.7 416 | esbuild-openbsd-64: 0.15.7 417 | esbuild-sunos-64: 0.15.7 418 | esbuild-windows-32: 0.15.7 419 | esbuild-windows-64: 0.15.7 420 | esbuild-windows-arm64: 0.15.7 421 | dev: true 422 | 423 | /estree-walker/2.0.2: 424 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 425 | dev: true 426 | 427 | /fast-glob/3.2.12: 428 | resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} 429 | engines: {node: '>=8.6.0'} 430 | dependencies: 431 | '@nodelib/fs.stat': 2.0.5 432 | '@nodelib/fs.walk': 1.2.8 433 | glob-parent: 5.1.2 434 | merge2: 1.4.1 435 | micromatch: 4.0.5 436 | dev: true 437 | 438 | /fastq/1.13.0: 439 | resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} 440 | dependencies: 441 | reusify: 1.0.4 442 | dev: true 443 | 444 | /fill-range/7.0.1: 445 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 446 | engines: {node: '>=8'} 447 | dependencies: 448 | to-regex-range: 5.0.1 449 | dev: true 450 | 451 | /fs.realpath/1.0.0: 452 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 453 | dev: true 454 | 455 | /fsevents/2.3.2: 456 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 457 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 458 | os: [darwin] 459 | requiresBuild: true 460 | dev: true 461 | optional: true 462 | 463 | /function-bind/1.1.1: 464 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 465 | dev: true 466 | 467 | /glob-parent/5.1.2: 468 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 469 | engines: {node: '>= 6'} 470 | dependencies: 471 | is-glob: 4.0.3 472 | dev: true 473 | 474 | /glob/7.2.3: 475 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 476 | dependencies: 477 | fs.realpath: 1.0.0 478 | inflight: 1.0.6 479 | inherits: 2.0.4 480 | minimatch: 3.1.2 481 | once: 1.4.0 482 | path-is-absolute: 1.0.1 483 | dev: true 484 | 485 | /graceful-fs/4.2.10: 486 | resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} 487 | dev: true 488 | 489 | /has/1.0.3: 490 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 491 | engines: {node: '>= 0.4.0'} 492 | dependencies: 493 | function-bind: 1.1.1 494 | dev: true 495 | 496 | /import-fresh/3.3.0: 497 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 498 | engines: {node: '>=6'} 499 | dependencies: 500 | parent-module: 1.0.1 501 | resolve-from: 4.0.0 502 | dev: true 503 | 504 | /inflight/1.0.6: 505 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 506 | dependencies: 507 | once: 1.4.0 508 | wrappy: 1.0.2 509 | dev: true 510 | 511 | /inherits/2.0.4: 512 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 513 | dev: true 514 | 515 | /is-binary-path/2.1.0: 516 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 517 | engines: {node: '>=8'} 518 | dependencies: 519 | binary-extensions: 2.2.0 520 | dev: true 521 | 522 | /is-core-module/2.10.0: 523 | resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} 524 | dependencies: 525 | has: 1.0.3 526 | dev: true 527 | 528 | /is-extglob/2.1.1: 529 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 530 | engines: {node: '>=0.10.0'} 531 | dev: true 532 | 533 | /is-glob/4.0.3: 534 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 535 | engines: {node: '>=0.10.0'} 536 | dependencies: 537 | is-extglob: 2.1.1 538 | dev: true 539 | 540 | /is-number/7.0.0: 541 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 542 | engines: {node: '>=0.12.0'} 543 | dev: true 544 | 545 | /kleur/4.1.5: 546 | resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} 547 | engines: {node: '>=6'} 548 | dev: true 549 | 550 | /magic-string/0.25.9: 551 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} 552 | dependencies: 553 | sourcemap-codec: 1.4.8 554 | dev: true 555 | 556 | /magic-string/0.26.3: 557 | resolution: {integrity: sha512-u1Po0NDyFcwdg2nzHT88wSK0+Rih0N1M+Ph1Sp08k8yvFFU3KR72wryS7e1qMPJypt99WB7fIFVCA92mQrMjrg==} 558 | engines: {node: '>=12'} 559 | dependencies: 560 | sourcemap-codec: 1.4.8 561 | dev: true 562 | 563 | /merge2/1.4.1: 564 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 565 | engines: {node: '>= 8'} 566 | dev: true 567 | 568 | /micromatch/4.0.5: 569 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 570 | engines: {node: '>=8.6'} 571 | dependencies: 572 | braces: 3.0.2 573 | picomatch: 2.3.1 574 | dev: true 575 | 576 | /min-indent/1.0.1: 577 | resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} 578 | engines: {node: '>=4'} 579 | dev: true 580 | 581 | /minimatch/3.1.2: 582 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 583 | dependencies: 584 | brace-expansion: 1.1.11 585 | dev: true 586 | 587 | /minimist/1.2.6: 588 | resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} 589 | dev: true 590 | 591 | /mkdirp/0.5.6: 592 | resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} 593 | hasBin: true 594 | dependencies: 595 | minimist: 1.2.6 596 | dev: true 597 | 598 | /mri/1.2.0: 599 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 600 | engines: {node: '>=4'} 601 | dev: true 602 | 603 | /ms/2.1.2: 604 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 605 | dev: true 606 | 607 | /nanoid/3.3.4: 608 | resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} 609 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 610 | hasBin: true 611 | dev: true 612 | 613 | /normalize-path/3.0.0: 614 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 615 | engines: {node: '>=0.10.0'} 616 | dev: true 617 | 618 | /once/1.4.0: 619 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 620 | dependencies: 621 | wrappy: 1.0.2 622 | dev: true 623 | 624 | /parent-module/1.0.1: 625 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 626 | engines: {node: '>=6'} 627 | dependencies: 628 | callsites: 3.1.0 629 | dev: true 630 | 631 | /path-is-absolute/1.0.1: 632 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 633 | engines: {node: '>=0.10.0'} 634 | dev: true 635 | 636 | /path-parse/1.0.7: 637 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 638 | dev: true 639 | 640 | /picocolors/1.0.0: 641 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 642 | dev: true 643 | 644 | /picomatch/2.3.1: 645 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 646 | engines: {node: '>=8.6'} 647 | dev: true 648 | 649 | /postcss/8.4.16: 650 | resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==} 651 | engines: {node: ^10 || ^12 || >=14} 652 | dependencies: 653 | nanoid: 3.3.4 654 | picocolors: 1.0.0 655 | source-map-js: 1.0.2 656 | dev: true 657 | 658 | /queue-microtask/1.2.3: 659 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 660 | dev: true 661 | 662 | /readdirp/3.6.0: 663 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 664 | engines: {node: '>=8.10.0'} 665 | dependencies: 666 | picomatch: 2.3.1 667 | dev: true 668 | 669 | /resolve-from/4.0.0: 670 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 671 | engines: {node: '>=4'} 672 | dev: true 673 | 674 | /resolve/1.22.1: 675 | resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} 676 | hasBin: true 677 | dependencies: 678 | is-core-module: 2.10.0 679 | path-parse: 1.0.7 680 | supports-preserve-symlinks-flag: 1.0.0 681 | dev: true 682 | 683 | /reusify/1.0.4: 684 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 685 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 686 | dev: true 687 | 688 | /rimraf/2.7.1: 689 | resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} 690 | hasBin: true 691 | dependencies: 692 | glob: 7.2.3 693 | dev: true 694 | 695 | /rollup/2.78.1: 696 | resolution: {integrity: sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==} 697 | engines: {node: '>=10.0.0'} 698 | hasBin: true 699 | optionalDependencies: 700 | fsevents: 2.3.2 701 | dev: true 702 | 703 | /run-parallel/1.2.0: 704 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 705 | dependencies: 706 | queue-microtask: 1.2.3 707 | dev: true 708 | 709 | /sade/1.8.1: 710 | resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} 711 | engines: {node: '>=6'} 712 | dependencies: 713 | mri: 1.2.0 714 | dev: true 715 | 716 | /sander/0.5.1: 717 | resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} 718 | dependencies: 719 | es6-promise: 3.3.1 720 | graceful-fs: 4.2.10 721 | mkdirp: 0.5.6 722 | rimraf: 2.7.1 723 | dev: true 724 | 725 | /sorcery/0.10.0: 726 | resolution: {integrity: sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==} 727 | hasBin: true 728 | dependencies: 729 | buffer-crc32: 0.2.13 730 | minimist: 1.2.6 731 | sander: 0.5.1 732 | sourcemap-codec: 1.4.8 733 | dev: true 734 | 735 | /source-map-js/1.0.2: 736 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 737 | engines: {node: '>=0.10.0'} 738 | dev: true 739 | 740 | /sourcemap-codec/1.4.8: 741 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 742 | dev: true 743 | 744 | /strip-indent/3.0.0: 745 | resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} 746 | engines: {node: '>=8'} 747 | dependencies: 748 | min-indent: 1.0.1 749 | dev: true 750 | 751 | /supports-preserve-symlinks-flag/1.0.0: 752 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 753 | engines: {node: '>= 0.4'} 754 | dev: true 755 | 756 | /svelte-check/2.9.0_svelte@3.50.1: 757 | resolution: {integrity: sha512-9AVrtP7WbfDgCdqTZNPdj5CCCy1OrYMxFVWAWzNw7fl93c9klFJFtqzVXa6fovfQ050CcpUyJE2dPFL9TFAREw==} 758 | hasBin: true 759 | peerDependencies: 760 | svelte: ^3.24.0 761 | dependencies: 762 | '@jridgewell/trace-mapping': 0.3.15 763 | chokidar: 3.5.3 764 | fast-glob: 3.2.12 765 | import-fresh: 3.3.0 766 | picocolors: 1.0.0 767 | sade: 1.8.1 768 | svelte: 3.50.1 769 | svelte-preprocess: 4.10.7_iprco5tylfmvffqgrvqxc46njy 770 | typescript: 4.8.3 771 | transitivePeerDependencies: 772 | - '@babel/core' 773 | - coffeescript 774 | - less 775 | - node-sass 776 | - postcss 777 | - postcss-load-config 778 | - pug 779 | - sass 780 | - stylus 781 | - sugarss 782 | dev: true 783 | 784 | /svelte-hmr/0.14.12_svelte@3.50.1: 785 | resolution: {integrity: sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==} 786 | engines: {node: ^12.20 || ^14.13.1 || >= 16} 787 | peerDependencies: 788 | svelte: '>=3.19.0' 789 | dependencies: 790 | svelte: 3.50.1 791 | dev: true 792 | 793 | /svelte-preprocess/4.10.7_iprco5tylfmvffqgrvqxc46njy: 794 | resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==} 795 | engines: {node: '>= 9.11.2'} 796 | requiresBuild: true 797 | peerDependencies: 798 | '@babel/core': ^7.10.2 799 | coffeescript: ^2.5.1 800 | less: ^3.11.3 || ^4.0.0 801 | node-sass: '*' 802 | postcss: ^7 || ^8 803 | postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 804 | pug: ^3.0.0 805 | sass: ^1.26.8 806 | stylus: ^0.55.0 807 | sugarss: ^2.0.0 808 | svelte: ^3.23.0 809 | typescript: ^3.9.5 || ^4.0.0 810 | peerDependenciesMeta: 811 | '@babel/core': 812 | optional: true 813 | coffeescript: 814 | optional: true 815 | less: 816 | optional: true 817 | node-sass: 818 | optional: true 819 | postcss: 820 | optional: true 821 | postcss-load-config: 822 | optional: true 823 | pug: 824 | optional: true 825 | sass: 826 | optional: true 827 | stylus: 828 | optional: true 829 | sugarss: 830 | optional: true 831 | typescript: 832 | optional: true 833 | dependencies: 834 | '@types/pug': 2.0.6 835 | '@types/sass': 1.43.1 836 | detect-indent: 6.1.0 837 | magic-string: 0.25.9 838 | sorcery: 0.10.0 839 | strip-indent: 3.0.0 840 | svelte: 3.50.1 841 | typescript: 4.8.3 842 | dev: true 843 | 844 | /svelte/3.50.1: 845 | resolution: {integrity: sha512-bS4odcsdj5D5jEg6riZuMg5NKelzPtmsCbD9RG+8umU03TeNkdWnP6pqbCm0s8UQNBkqk29w/Bdubn3C+HWSwA==} 846 | engines: {node: '>= 8'} 847 | dev: true 848 | 849 | /to-regex-range/5.0.1: 850 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 851 | engines: {node: '>=8.0'} 852 | dependencies: 853 | is-number: 7.0.0 854 | dev: true 855 | 856 | /tslib/2.4.0: 857 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} 858 | dev: true 859 | 860 | /typescript/4.8.3: 861 | resolution: {integrity: sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==} 862 | engines: {node: '>=4.2.0'} 863 | hasBin: true 864 | dev: true 865 | 866 | /vite/3.1.0: 867 | resolution: {integrity: sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==} 868 | engines: {node: ^14.18.0 || >=16.0.0} 869 | hasBin: true 870 | peerDependencies: 871 | less: '*' 872 | sass: '*' 873 | stylus: '*' 874 | terser: ^5.4.0 875 | peerDependenciesMeta: 876 | less: 877 | optional: true 878 | sass: 879 | optional: true 880 | stylus: 881 | optional: true 882 | terser: 883 | optional: true 884 | dependencies: 885 | esbuild: 0.15.7 886 | postcss: 8.4.16 887 | resolve: 1.22.1 888 | rollup: 2.78.1 889 | optionalDependencies: 890 | fsevents: 2.3.2 891 | dev: true 892 | 893 | /wrappy/1.0.2: 894 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 895 | dev: true 896 | -------------------------------------------------------------------------------- /marketplace/public/GitHub-Mark-Light-64px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lapce/lapce-extensions/5f8f95aff4c481adec055279510dfafae2c5c3c0/marketplace/public/GitHub-Mark-Light-64px.png -------------------------------------------------------------------------------- /marketplace/public/lapce-30px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lapce/lapce-extensions/5f8f95aff4c481adec055279510dfafae2c5c3c0/marketplace/public/lapce-30px.png -------------------------------------------------------------------------------- /marketplace/public/lapce-35px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lapce/lapce-extensions/5f8f95aff4c481adec055279510dfafae2c5c3c0/marketplace/public/lapce-35px.png -------------------------------------------------------------------------------- /marketplace/public/lapce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lapce/lapce-extensions/5f8f95aff4c481adec055279510dfafae2c5c3c0/marketplace/public/lapce.png -------------------------------------------------------------------------------- /marketplace/src/App.svelte: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /marketplace/src/app.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap'); 3 | :root { 4 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 5 | } 6 | html, body { 7 | margin: 0; 8 | padding: 0; 9 | } 10 | h1 { 11 | margin: 0 0; 12 | } -------------------------------------------------------------------------------- /marketplace/src/components/NavBar.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /marketplace/src/components/Sticky.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 31 |
32 | 33 |
34 | -------------------------------------------------------------------------------- /marketplace/src/components/UserIndicator.svelte: -------------------------------------------------------------------------------- 1 | 33 | 34 | {#if logged_in} 35 |
36 | pfp 42 | {user.name} 43 | 44 |
45 | {:else} 46 | 54 | {/if} 55 | 100 | -------------------------------------------------------------------------------- /marketplace/src/main.ts: -------------------------------------------------------------------------------- 1 | import './app.css' 2 | import App from './App.svelte' 3 | 4 | const app = new App({ 5 | target: document.getElementById('app') 6 | }) 7 | export default app 8 | -------------------------------------------------------------------------------- /marketplace/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /marketplace/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 | -------------------------------------------------------------------------------- /marketplace/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 | -------------------------------------------------------------------------------- /marketplace/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /marketplace/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 | build: { 8 | sourcemap: true, 9 | }, 10 | }) 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "postinstall": "cd marketplace && npm install && npm run build && cd .." 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /prisma/migrations/20221009190213_user/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "User" ( 3 | "id" INTEGER NOT NULL, 4 | "name" TEXT NOT NULL, 5 | "username" TEXT NOT NULL, 6 | "avatar_url" TEXT NOT NULL, 7 | 8 | CONSTRAINT "User_pkey" PRIMARY KEY ("id") 9 | ); 10 | -------------------------------------------------------------------------------- /prisma/migrations/20221009192036_change_id_int_to_bigint/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - The primary key for the `User` table will be changed. If it partially fails, the table could be left without primary key constraint. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "User" DROP CONSTRAINT "User_pkey", 9 | ALTER COLUMN "id" SET DATA TYPE BIGINT, 10 | ADD CONSTRAINT "User_pkey" PRIMARY KEY ("id"); 11 | -------------------------------------------------------------------------------- /prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | generator client { 4 | // Corresponds to the cargo alias created earlier 5 | provider = "target/release/prisma_cli" 6 | // The location to generate the client. Is relative to the position of the schema 7 | output = "../src/db/prisma.rs" 8 | } 9 | 10 | datasource db { 11 | provider = "postgresql" 12 | url = env("DATABASE_URL") 13 | } 14 | model User { 15 | id BigInt @id 16 | name String 17 | username String 18 | avatar_url String 19 | } 20 | -------------------------------------------------------------------------------- /prisma_cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "prisma_cli" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | prisma-client-rust-cli = { git = "https://github.com/Brendonovich/prisma-client-rust", tag = "0.6.1" } 10 | 11 | -------------------------------------------------------------------------------- /prisma_cli/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | prisma_client_rust_cli::run(); 3 | } 4 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly 2 | -------------------------------------------------------------------------------- /scripts/build-frontend.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd marketplace 3 | nodemon 4 | -------------------------------------------------------------------------------- /scripts/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if type flatpak-spawn >/dev/null 2>&1 ; 3 | then 4 | DOCKER="flatpak-spawn --host docker" 5 | DOCKER_COMPOSE="flatpak-spawn --host docker-compose" 6 | else 7 | DOCKER="docker" 8 | DOCKER_COMPOSE="docker-compose" 9 | fi 10 | 11 | function stop() { 12 | pkill cargo-watch 13 | $DOCKER_COMPOSE stop 14 | } 15 | if [ -z "$($DOCKER_COMPOSE top)" ]; 16 | then 17 | echo "[INFO] Starting microservices" 18 | $DOCKER_COMPOSE up -d 19 | else 20 | echo "[INFO] Restarting microservices because they're already up" 21 | $DOCKER_COMPOSE restart 22 | fi 23 | echo "[INFO] Waiting 2s for the database to start" 24 | sleep 2s 25 | echo "[INFO] Running migrations" 26 | cargo prisma db push 27 | echo "[INFO] Setting shutdown trap" 28 | trap stop 1 3 9 2 29 | echo "[INFO] Starting backend" 30 | cargo watch -x "run --bin server" -w server 31 | -------------------------------------------------------------------------------- /src/db.rs: -------------------------------------------------------------------------------- 1 | pub mod prisma; 2 | use dotenvy::dotenv; 3 | use prisma::PrismaClient; 4 | use crate::error::{Error, ErrorKind}; 5 | 6 | pub async fn establish_connection() -> Result { 7 | dotenv().ok(); 8 | let res = prisma::new_client().await; 9 | 10 | match res { 11 | Ok(con) => { 12 | Ok(con) 13 | } 14 | Err(err) => { 15 | Err(Error{ 16 | message: "Couldn't connect to the database".into(), 17 | action: "Try again later, or if you're the admin, check the database".into(), 18 | kind: ErrorKind::DatabaseError(err.to_string()) 19 | }) 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/db/prisma.rs: -------------------------------------------------------------------------------- 1 | // Code generated by Prisma Client Rust. DO NOT EDIT 2 | 3 | #![allow(warnings, unused)] 4 | static DATAMODEL_STR : & 'static str = "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\ngenerator client {\n // Corresponds to the cargo alias created earlier\n provider = \"cargo prisma\"\n // The location to generate the client. Is relative to the position of the schema\n output = \"../src/db/prisma.rs\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n url = env(\"DATABASE_URL\")\n}\nmodel User {\n\tid BigInt @id\n\tname String\n\tusername String\n\tavatar_url String\n}\n" ; 5 | static DATABASE_STR: &'static str = "postgresql"; 6 | pub async fn new_client() -> Result { 7 | let config = ::prisma_client_rust::datamodel::parse_configuration(DATAMODEL_STR)?.subject; 8 | let source = config 9 | .datasources 10 | .first() 11 | .expect("Please supply a datasource in your schema.prisma file"); 12 | let url = if let Some(url) = source.load_shadow_database_url()? { 13 | url 14 | } else { 15 | source.load_url(|key| std::env::var(key).ok())? 16 | }; 17 | let url = if url.starts_with("file:") { 18 | let path = url.split(":").nth(1).unwrap(); 19 | if std::path::Path::new("./schema.prisma").exists() { 20 | url 21 | } else if std::path::Path::new("./prisma/schema.prisma").exists() { 22 | format!("file:./prisma/{}", path) 23 | } else { 24 | url 25 | } 26 | } else { 27 | url 28 | }; 29 | new_client_with_url(&url).await 30 | } 31 | pub async fn new_client_with_url( 32 | url: &str, 33 | ) -> Result { 34 | let config = ::prisma_client_rust::datamodel::parse_configuration(DATAMODEL_STR)?.subject; 35 | let source = config 36 | .datasources 37 | .first() 38 | .expect("Please supply a datasource in your schema.prisma file"); 39 | let (db_name, executor) = 40 | ::prisma_client_rust::query_core::executor::load(&source, &[], &url).await?; 41 | let internal_model = 42 | ::prisma_client_rust::prisma_models::InternalDataModelBuilder::new(DATAMODEL_STR) 43 | .build(db_name); 44 | let query_schema = std::sync::Arc::new(prisma_client_rust::query_core::schema_builder::build( 45 | internal_model, 46 | true, 47 | source.capabilities(), 48 | vec![], 49 | source.referential_integrity(), 50 | )); 51 | executor.primary_connector().get_connection().await?; 52 | Ok(PrismaClient::_new(executor, query_schema)) 53 | } 54 | pub mod user { 55 | use super::_prisma::*; 56 | use super::*; 57 | pub mod id { 58 | use super::super::*; 59 | use super::_prisma::*; 60 | use super::{OrderByParam, SetParam, UniqueWhereParam, WhereParam, WithParam}; 61 | pub fn set>(value: i64) -> T { 62 | Set(value).into() 63 | } 64 | pub fn equals>(value: i64) -> T { 65 | UniqueWhereParam::IdEquals(value).into() 66 | } 67 | pub fn order(direction: ::prisma_client_rust::Direction) -> OrderByParam { 68 | OrderByParam::Id(direction) 69 | } 70 | pub fn in_vec(value: Vec) -> WhereParam { 71 | WhereParam::IdInVec(value) 72 | } 73 | pub fn not_in_vec(value: Vec) -> WhereParam { 74 | WhereParam::IdNotInVec(value) 75 | } 76 | pub fn lt(value: i64) -> WhereParam { 77 | WhereParam::IdLt(value) 78 | } 79 | pub fn lte(value: i64) -> WhereParam { 80 | WhereParam::IdLte(value) 81 | } 82 | pub fn gt(value: i64) -> WhereParam { 83 | WhereParam::IdGt(value) 84 | } 85 | pub fn gte(value: i64) -> WhereParam { 86 | WhereParam::IdGte(value) 87 | } 88 | pub fn not(value: i64) -> WhereParam { 89 | WhereParam::IdNot(value) 90 | } 91 | pub fn increment(value: i64) -> SetParam { 92 | SetParam::IncrementId(value) 93 | } 94 | pub fn decrement(value: i64) -> SetParam { 95 | SetParam::DecrementId(value) 96 | } 97 | pub fn multiply(value: i64) -> SetParam { 98 | SetParam::MultiplyId(value) 99 | } 100 | pub fn divide(value: i64) -> SetParam { 101 | SetParam::DivideId(value) 102 | } 103 | pub struct Set(pub i64); 104 | impl From for SetParam { 105 | fn from(value: Set) -> Self { 106 | Self::SetId(value.0) 107 | } 108 | } 109 | pub struct Include; 110 | impl Into for Include { 111 | fn into(self) -> super::IncludeParam { 112 | super::IncludeParam::Id(self) 113 | } 114 | } 115 | impl Include { 116 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 117 | ::prisma_client_rust::Selection::builder("id").build() 118 | } 119 | } 120 | pub struct Select; 121 | impl Into for Select { 122 | fn into(self) -> super::SelectParam { 123 | super::SelectParam::Id(self) 124 | } 125 | } 126 | impl Select { 127 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 128 | ::prisma_client_rust::Selection::builder("id").build() 129 | } 130 | } 131 | } 132 | pub mod name { 133 | use super::super::*; 134 | use super::_prisma::*; 135 | use super::{OrderByParam, SetParam, UniqueWhereParam, WhereParam, WithParam}; 136 | pub fn set>(value: String) -> T { 137 | Set(value).into() 138 | } 139 | pub fn equals(value: String) -> WhereParam { 140 | WhereParam::NameEquals(value).into() 141 | } 142 | pub fn order(direction: ::prisma_client_rust::Direction) -> OrderByParam { 143 | OrderByParam::Name(direction) 144 | } 145 | pub fn in_vec(value: Vec) -> WhereParam { 146 | WhereParam::NameInVec(value) 147 | } 148 | pub fn not_in_vec(value: Vec) -> WhereParam { 149 | WhereParam::NameNotInVec(value) 150 | } 151 | pub fn lt(value: String) -> WhereParam { 152 | WhereParam::NameLt(value) 153 | } 154 | pub fn lte(value: String) -> WhereParam { 155 | WhereParam::NameLte(value) 156 | } 157 | pub fn gt(value: String) -> WhereParam { 158 | WhereParam::NameGt(value) 159 | } 160 | pub fn gte(value: String) -> WhereParam { 161 | WhereParam::NameGte(value) 162 | } 163 | pub fn contains(value: String) -> WhereParam { 164 | WhereParam::NameContains(value) 165 | } 166 | pub fn starts_with(value: String) -> WhereParam { 167 | WhereParam::NameStartsWith(value) 168 | } 169 | pub fn ends_with(value: String) -> WhereParam { 170 | WhereParam::NameEndsWith(value) 171 | } 172 | pub fn mode(value: QueryMode) -> WhereParam { 173 | WhereParam::NameMode(value) 174 | } 175 | pub fn not(value: String) -> WhereParam { 176 | WhereParam::NameNot(value) 177 | } 178 | pub struct Set(pub String); 179 | impl From for SetParam { 180 | fn from(value: Set) -> Self { 181 | Self::SetName(value.0) 182 | } 183 | } 184 | pub struct Include; 185 | impl Into for Include { 186 | fn into(self) -> super::IncludeParam { 187 | super::IncludeParam::Name(self) 188 | } 189 | } 190 | impl Include { 191 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 192 | ::prisma_client_rust::Selection::builder("name").build() 193 | } 194 | } 195 | pub struct Select; 196 | impl Into for Select { 197 | fn into(self) -> super::SelectParam { 198 | super::SelectParam::Name(self) 199 | } 200 | } 201 | impl Select { 202 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 203 | ::prisma_client_rust::Selection::builder("name").build() 204 | } 205 | } 206 | } 207 | pub mod username { 208 | use super::super::*; 209 | use super::_prisma::*; 210 | use super::{OrderByParam, SetParam, UniqueWhereParam, WhereParam, WithParam}; 211 | pub fn set>(value: String) -> T { 212 | Set(value).into() 213 | } 214 | pub fn equals(value: String) -> WhereParam { 215 | WhereParam::UsernameEquals(value).into() 216 | } 217 | pub fn order(direction: ::prisma_client_rust::Direction) -> OrderByParam { 218 | OrderByParam::Username(direction) 219 | } 220 | pub fn in_vec(value: Vec) -> WhereParam { 221 | WhereParam::UsernameInVec(value) 222 | } 223 | pub fn not_in_vec(value: Vec) -> WhereParam { 224 | WhereParam::UsernameNotInVec(value) 225 | } 226 | pub fn lt(value: String) -> WhereParam { 227 | WhereParam::UsernameLt(value) 228 | } 229 | pub fn lte(value: String) -> WhereParam { 230 | WhereParam::UsernameLte(value) 231 | } 232 | pub fn gt(value: String) -> WhereParam { 233 | WhereParam::UsernameGt(value) 234 | } 235 | pub fn gte(value: String) -> WhereParam { 236 | WhereParam::UsernameGte(value) 237 | } 238 | pub fn contains(value: String) -> WhereParam { 239 | WhereParam::UsernameContains(value) 240 | } 241 | pub fn starts_with(value: String) -> WhereParam { 242 | WhereParam::UsernameStartsWith(value) 243 | } 244 | pub fn ends_with(value: String) -> WhereParam { 245 | WhereParam::UsernameEndsWith(value) 246 | } 247 | pub fn mode(value: QueryMode) -> WhereParam { 248 | WhereParam::UsernameMode(value) 249 | } 250 | pub fn not(value: String) -> WhereParam { 251 | WhereParam::UsernameNot(value) 252 | } 253 | pub struct Set(pub String); 254 | impl From for SetParam { 255 | fn from(value: Set) -> Self { 256 | Self::SetUsername(value.0) 257 | } 258 | } 259 | pub struct Include; 260 | impl Into for Include { 261 | fn into(self) -> super::IncludeParam { 262 | super::IncludeParam::Username(self) 263 | } 264 | } 265 | impl Include { 266 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 267 | ::prisma_client_rust::Selection::builder("username").build() 268 | } 269 | } 270 | pub struct Select; 271 | impl Into for Select { 272 | fn into(self) -> super::SelectParam { 273 | super::SelectParam::Username(self) 274 | } 275 | } 276 | impl Select { 277 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 278 | ::prisma_client_rust::Selection::builder("username").build() 279 | } 280 | } 281 | } 282 | pub mod avatar_url { 283 | use super::super::*; 284 | use super::_prisma::*; 285 | use super::{OrderByParam, SetParam, UniqueWhereParam, WhereParam, WithParam}; 286 | pub fn set>(value: String) -> T { 287 | Set(value).into() 288 | } 289 | pub fn equals(value: String) -> WhereParam { 290 | WhereParam::AvatarUrlEquals(value).into() 291 | } 292 | pub fn order(direction: ::prisma_client_rust::Direction) -> OrderByParam { 293 | OrderByParam::AvatarUrl(direction) 294 | } 295 | pub fn in_vec(value: Vec) -> WhereParam { 296 | WhereParam::AvatarUrlInVec(value) 297 | } 298 | pub fn not_in_vec(value: Vec) -> WhereParam { 299 | WhereParam::AvatarUrlNotInVec(value) 300 | } 301 | pub fn lt(value: String) -> WhereParam { 302 | WhereParam::AvatarUrlLt(value) 303 | } 304 | pub fn lte(value: String) -> WhereParam { 305 | WhereParam::AvatarUrlLte(value) 306 | } 307 | pub fn gt(value: String) -> WhereParam { 308 | WhereParam::AvatarUrlGt(value) 309 | } 310 | pub fn gte(value: String) -> WhereParam { 311 | WhereParam::AvatarUrlGte(value) 312 | } 313 | pub fn contains(value: String) -> WhereParam { 314 | WhereParam::AvatarUrlContains(value) 315 | } 316 | pub fn starts_with(value: String) -> WhereParam { 317 | WhereParam::AvatarUrlStartsWith(value) 318 | } 319 | pub fn ends_with(value: String) -> WhereParam { 320 | WhereParam::AvatarUrlEndsWith(value) 321 | } 322 | pub fn mode(value: QueryMode) -> WhereParam { 323 | WhereParam::AvatarUrlMode(value) 324 | } 325 | pub fn not(value: String) -> WhereParam { 326 | WhereParam::AvatarUrlNot(value) 327 | } 328 | pub struct Set(pub String); 329 | impl From for SetParam { 330 | fn from(value: Set) -> Self { 331 | Self::SetAvatarUrl(value.0) 332 | } 333 | } 334 | pub struct Include; 335 | impl Into for Include { 336 | fn into(self) -> super::IncludeParam { 337 | super::IncludeParam::AvatarUrl(self) 338 | } 339 | } 340 | impl Include { 341 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 342 | ::prisma_client_rust::Selection::builder("avatar_url").build() 343 | } 344 | } 345 | pub struct Select; 346 | impl Into for Select { 347 | fn into(self) -> super::SelectParam { 348 | super::SelectParam::AvatarUrl(self) 349 | } 350 | } 351 | impl Select { 352 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 353 | ::prisma_client_rust::Selection::builder("avatar_url").build() 354 | } 355 | } 356 | } 357 | pub fn _outputs() -> Vec<::prisma_client_rust::Selection> { 358 | ["id", "name", "username", "avatar_url"] 359 | .into_iter() 360 | .map(|o| { 361 | let builder = ::prisma_client_rust::Selection::builder(o); 362 | builder.build() 363 | }) 364 | .collect() 365 | } 366 | pub fn create( 367 | id: i64, 368 | name: String, 369 | username: String, 370 | avatar_url: String, 371 | _params: Vec, 372 | ) -> (i64, String, String, String, Vec) { 373 | (id, name, username, avatar_url, _params) 374 | } 375 | #[macro_export] 376 | macro_rules ! _select_user { ($ (($ ($ func_arg : ident : $ func_arg_ty : ty) , +) =>) ? $ module_name : ident { $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) + }) => { # [allow (warnings)] pub mod $ module_name { $ crate :: prisma :: user :: select ! (@ definitions ; $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) +) ; pub struct Select (Vec < :: prisma_client_rust :: Selection >) ; impl :: prisma_client_rust :: select :: SelectType for Select { type Data = Data ; type ModelData = $ crate :: prisma :: user :: Data ; fn to_selections (self) -> Vec < :: prisma_client_rust :: Selection > { self . 0 } } use super :: * ; pub fn select ($ ($ ($ func_arg : $ func_arg_ty) , +) ?) -> Select { Select ($ crate :: prisma :: user :: select ! (@ selections_to_select_params ; : select { $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) + }) . into_iter () . map (| p | p . to_selection ()) . collect ()) } } } ; ({ $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) + }) => { { $ crate :: prisma :: user :: select ! (@ definitions ; $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) +) ; pub struct Select (Vec < :: prisma_client_rust :: Selection >) ; impl :: prisma_client_rust :: select :: SelectType for Select { type Data = Data ; type ModelData = $ crate :: prisma :: user :: Data ; fn to_selections (self) -> Vec < :: prisma_client_rust :: Selection > { self . 0 } } Select ($ crate :: prisma :: user :: select ! (@ selections_to_select_params ; : select { $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) + }) . into_iter () . map (| p | p . to_selection ()) . collect ()) } } ; (@ definitions ; $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) +) => { # [allow (warnings)] enum Fields { id , name , username , avatar_url } # [allow (warnings)] impl Fields { fn selections () { $ (let _ = Fields :: $ field ;) + } } # [allow (warnings)] # [derive (std :: fmt :: Debug)] pub struct Data { $ (pub $ field : $ crate :: prisma :: user :: select ! (@ field_type ; $ field $ (: $ selection_mode { $ ($ selections) + }) ?) ,) + } impl :: serde :: Serialize for Data { fn serialize < S > (& self , serializer : S) -> Result < S :: Ok , S :: Error > where S : :: serde :: Serializer , { use :: serde :: ser :: SerializeStruct ; let mut state = serializer . serialize_struct ("Data" , [$ (stringify ! ($ field) ,) + stringify ! (id) , stringify ! (name) , stringify ! (username) , stringify ! (avatar_url)] . len ()) ? ; $ (state . serialize_field ($ crate :: prisma :: user :: select ! (@ field_serde_name ; $ field) , & self . $ field) ? ;) * state . end () } } impl < 'de > :: serde :: Deserialize < 'de > for Data { fn deserialize < D > (deserializer : D) -> Result < Self , D :: Error > where D : :: serde :: Deserializer < 'de > , { # [allow (warnings)] enum Field { $ ($ field) , + , } impl < 'de > :: serde :: Deserialize < 'de > for Field { fn deserialize < D > (deserializer : D) -> Result < Field , D :: Error > where D : :: serde :: Deserializer < 'de > , { struct FieldVisitor ; impl < 'de > :: serde :: de :: Visitor < 'de > for FieldVisitor { type Value = Field ; fn expecting (& self , formatter : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { formatter . write_str (concat ! ($ ($ crate :: prisma :: user :: select ! (@ field_serde_name ; $ field) , ", ") , +)) } fn visit_str < E > (self , value : & str) -> Result < Field , E > where E : :: serde :: de :: Error , { match value { $ ($ crate :: prisma :: user :: select ! (@ field_serde_name ; $ field) => Ok (Field :: $ field)) , * , _ => Err (:: serde :: de :: Error :: unknown_field (value , FIELDS)) , } } } deserializer . deserialize_identifier (FieldVisitor) } } struct DataVisitor ; impl < 'de > :: serde :: de :: Visitor < 'de > for DataVisitor { type Value = Data ; fn expecting (& self , formatter : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { formatter . write_str ("struct Data") } fn visit_map < V > (self , mut map : V) -> Result < Data , V :: Error > where V : :: serde :: de :: MapAccess < 'de > , { $ (let mut $ field = None ;) * while let Some (key) = map . next_key () ? { match key { $ (Field :: $ field => { if $ field . is_some () { return Err (:: serde :: de :: Error :: duplicate_field ($ crate :: prisma :: user :: select ! (@ field_serde_name ; $ field))) ; } $ field = Some (map . next_value () ?) ; }) * } } $ (let $ field = $ field . ok_or_else (|| serde :: de :: Error :: missing_field ($ crate :: prisma :: user :: select ! (@ field_serde_name ; $ field))) ? ;) * Ok (Data { $ ($ field) , * }) } } const FIELDS : & 'static [& 'static str] = & ["id" , "name" , "username" , "avatar_url"] ; deserializer . deserialize_struct ("Data" , FIELDS , DataVisitor) } } $ ($ (pub mod $ field { $ crate :: prisma :: user :: select ! (@ field_module ; $ field : $ selection_mode { $ ($ selections) + }) ; }) ?) + } ; (@ field_type ; id) => { i64 } ; (@ field_type ; name) => { String } ; (@ field_type ; username) => { String } ; (@ field_type ; avatar_url) => { String } ; (@ field_type ; $ field : ident $ ($ tokens : tt) *) => { compile_error ! (stringify ! (Cannot select field nonexistent field $ field on model "User" , available fields are "id, name, username, avatar_url")) } ; (@ field_module ; $ ($ tokens : tt) *) => { } ; (@ selection_field_to_selection_param ; id) => { Into :: < $ crate :: prisma :: user :: SelectParam > :: into ($ crate :: prisma :: user :: id :: Select) } ; (@ selection_field_to_selection_param ; name) => { Into :: < $ crate :: prisma :: user :: SelectParam > :: into ($ crate :: prisma :: user :: name :: Select) } ; (@ selection_field_to_selection_param ; username) => { Into :: < $ crate :: prisma :: user :: SelectParam > :: into ($ crate :: prisma :: user :: username :: Select) } ; (@ selection_field_to_selection_param ; avatar_url) => { Into :: < $ crate :: prisma :: user :: SelectParam > :: into ($ crate :: prisma :: user :: avatar_url :: Select) } ; (@ selection_field_to_selection_param ; $ ($ tokens : tt) *) => { compile_error ! (stringify ! ($ ($ tokens) *)) } ; (@ selections_to_select_params ; : $ macro_name : ident { $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) + }) => { [$ ($ crate :: prisma :: user :: $ macro_name ! (@ selection_field_to_selection_param ; $ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) ,) +] } ; (@ filters_to_args ;) => { vec ! [] } ; (@ filters_to_args ; $ ($ t : tt) *) => { $ ($ t) * } ; (@ field_serde_name ; id) => { "id" } ; (@ field_serde_name ; name) => { "name" } ; (@ field_serde_name ; username) => { "username" } ; (@ field_serde_name ; avatar_url) => { "avatar_url" } ; } 377 | pub use _select_user as select; 378 | pub enum SelectParam { 379 | Id(id::Select), 380 | Name(name::Select), 381 | Username(username::Select), 382 | AvatarUrl(avatar_url::Select), 383 | } 384 | impl SelectParam { 385 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 386 | match self { 387 | Self::Id(data) => data.to_selection(), 388 | Self::Name(data) => data.to_selection(), 389 | Self::Username(data) => data.to_selection(), 390 | Self::AvatarUrl(data) => data.to_selection(), 391 | } 392 | } 393 | } 394 | #[macro_export] 395 | macro_rules ! _include_user { ($ (($ ($ func_arg : ident : $ func_arg_ty : ty) , +) =>) ? $ module_name : ident { $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) + }) => { # [allow (warnings)] pub mod $ module_name { $ crate :: prisma :: user :: include ! (@ definitions ; $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) +) ; pub struct Include (Vec < :: prisma_client_rust :: Selection >) ; impl :: prisma_client_rust :: include :: IncludeType for Include { type Data = Data ; type ModelData = $ crate :: prisma :: user :: Data ; fn to_selections (self) -> Vec < :: prisma_client_rust :: Selection > { self . 0 } } use super :: * ; pub fn include ($ ($ ($ func_arg : $ func_arg_ty) , +) ?) -> Include { let mut selections = $ crate :: prisma :: user :: _outputs () ; selections . extend ($ crate :: prisma :: user :: include ! (@ selections_to_include_params ; : include { $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) + }) . into_iter () . map (| p | p . to_selection ())) ; Include (selections) } } } ; ({ $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) + }) => { { $ crate :: prisma :: user :: include ! (@ definitions ; $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) +) ; pub struct Include (Vec < :: prisma_client_rust :: Selection >) ; impl :: prisma_client_rust :: include :: IncludeType for Include { type Data = Data ; type ModelData = $ crate :: prisma :: user :: Data ; fn to_selections (self) -> Vec < :: prisma_client_rust :: Selection > { self . 0 } } Include ({ let mut selections = $ crate :: prisma :: user :: _outputs () ; selections . extend ($ crate :: prisma :: user :: include ! (@ selections_to_include_params ; : include { $ ($ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) + }) . into_iter () . map (| p | p . to_selection ())) ; selections }) } } ; (@ definitions ; $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) +) => { # [allow (warnings)] enum Fields { } # [allow (warnings)] impl Fields { fn selections () { $ (let _ = Fields :: $ field ;) + } } # [allow (warnings)] # [derive (std :: fmt :: Debug)] pub struct Data { pub id : i64 , pub name : String , pub username : String , pub avatar_url : String , $ (pub $ field : $ crate :: prisma :: user :: include ! (@ field_type ; $ field $ (: $ selection_mode { $ ($ selections) + }) ?) ,) + } impl :: serde :: Serialize for Data { fn serialize < S > (& self , serializer : S) -> Result < S :: Ok , S :: Error > where S : :: serde :: Serializer , { use :: serde :: ser :: SerializeStruct ; let mut state = serializer . serialize_struct ("Data" , [$ (stringify ! ($ field) ,) + stringify ! (id) , stringify ! (name) , stringify ! (username) , stringify ! (avatar_url)] . len ()) ? ; $ (state . serialize_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; $ field) , & self . $ field) ? ;) * state . serialize_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; id) , & self . id) ? ; state . serialize_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; name) , & self . name) ? ; state . serialize_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; username) , & self . username) ? ; state . serialize_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; avatar_url) , & self . avatar_url) ? ; state . end () } } impl < 'de > :: serde :: Deserialize < 'de > for Data { fn deserialize < D > (deserializer : D) -> Result < Self , D :: Error > where D : :: serde :: Deserializer < 'de > , { # [allow (warnings)] enum Field { $ ($ field) , + , id , name , username , avatar_url } impl < 'de > :: serde :: Deserialize < 'de > for Field { fn deserialize < D > (deserializer : D) -> Result < Field , D :: Error > where D : :: serde :: Deserializer < 'de > , { struct FieldVisitor ; impl < 'de > :: serde :: de :: Visitor < 'de > for FieldVisitor { type Value = Field ; fn expecting (& self , formatter : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { formatter . write_str (concat ! ($ ($ crate :: prisma :: user :: include ! (@ field_serde_name ; $ field) , ", ") , + , $ crate :: prisma :: user :: include ! (@ field_serde_name ; id) , ", " , $ crate :: prisma :: user :: include ! (@ field_serde_name ; name) , ", " , $ crate :: prisma :: user :: include ! (@ field_serde_name ; username) , ", " , $ crate :: prisma :: user :: include ! (@ field_serde_name ; avatar_url) , ", ")) } fn visit_str < E > (self , value : & str) -> Result < Field , E > where E : :: serde :: de :: Error , { match value { $ ($ crate :: prisma :: user :: include ! (@ field_serde_name ; $ field) => Ok (Field :: $ field)) , * , $ crate :: prisma :: user :: include ! (@ field_serde_name ; id) => Ok (Field :: id) , $ crate :: prisma :: user :: include ! (@ field_serde_name ; name) => Ok (Field :: name) , $ crate :: prisma :: user :: include ! (@ field_serde_name ; username) => Ok (Field :: username) , $ crate :: prisma :: user :: include ! (@ field_serde_name ; avatar_url) => Ok (Field :: avatar_url) , _ => Err (:: serde :: de :: Error :: unknown_field (value , FIELDS)) , } } } deserializer . deserialize_identifier (FieldVisitor) } } struct DataVisitor ; impl < 'de > :: serde :: de :: Visitor < 'de > for DataVisitor { type Value = Data ; fn expecting (& self , formatter : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { formatter . write_str ("struct Data") } fn visit_map < V > (self , mut map : V) -> Result < Data , V :: Error > where V : :: serde :: de :: MapAccess < 'de > , { $ (let mut $ field = None ;) * let mut id = None ; let mut name = None ; let mut username = None ; let mut avatar_url = None ; while let Some (key) = map . next_key () ? { match key { Field :: id => { if id . is_some () { return Err (:: serde :: de :: Error :: duplicate_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; id))) ; } id = Some (map . next_value () ?) ; } Field :: name => { if name . is_some () { return Err (:: serde :: de :: Error :: duplicate_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; name))) ; } name = Some (map . next_value () ?) ; } Field :: username => { if username . is_some () { return Err (:: serde :: de :: Error :: duplicate_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; username))) ; } username = Some (map . next_value () ?) ; } Field :: avatar_url => { if avatar_url . is_some () { return Err (:: serde :: de :: Error :: duplicate_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; avatar_url))) ; } avatar_url = Some (map . next_value () ?) ; } $ (Field :: $ field => { if $ field . is_some () { return Err (:: serde :: de :: Error :: duplicate_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; $ field))) ; } $ field = Some (map . next_value () ?) ; }) * } } $ (let $ field = $ field . ok_or_else (|| serde :: de :: Error :: missing_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; $ field))) ? ;) * let id = id . ok_or_else (|| serde :: de :: Error :: missing_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; id))) ? ; let name = name . ok_or_else (|| serde :: de :: Error :: missing_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; name))) ? ; let username = username . ok_or_else (|| serde :: de :: Error :: missing_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; username))) ? ; let avatar_url = avatar_url . ok_or_else (|| serde :: de :: Error :: missing_field ($ crate :: prisma :: user :: include ! (@ field_serde_name ; avatar_url))) ? ; Ok (Data { id , name , username , avatar_url , $ ($ field) , * }) } } const FIELDS : & 'static [& 'static str] = & ["id" , "name" , "username" , "avatar_url"] ; deserializer . deserialize_struct ("Data" , FIELDS , DataVisitor) } } $ ($ (pub mod $ field { $ crate :: prisma :: user :: $ selection_mode ! (@ field_module ; $ field : $ selection_mode { $ ($ selections) + }) ; }) ?) + } ; (@ field_type ; $ field : ident $ ($ tokens : tt) *) => { compile_error ! (stringify ! (Cannot include nonexistent relation $ field on model "User" , available relations are "")) } ; (@ field_module ; $ ($ tokens : tt) *) => { } ; (@ selection_field_to_selection_param ; $ ($ tokens : tt) *) => { compile_error ! (stringify ! ($ ($ tokens) *)) } ; (@ selections_to_include_params ; : $ macro_name : ident { $ ($ field : ident $ (($ ($ filters : tt) +) $ (. $ arg : ident ($ ($ arg_params : tt) *)) *) ? $ (: $ selection_mode : ident { $ ($ selections : tt) + }) ?) + }) => { [$ ($ crate :: prisma :: user :: $ macro_name ! (@ selection_field_to_selection_param ; $ field $ (($ ($ filters) +) $ (. $ arg ($ ($ arg_params) *)) *) ? $ (: $ selection_mode { $ ($ selections) + }) ?) ,) +] } ; (@ filters_to_args ;) => { vec ! [] } ; (@ filters_to_args ; $ ($ t : tt) *) => { $ ($ t) * } ; (@ field_serde_name ; id) => { "id" } ; (@ field_serde_name ; name) => { "name" } ; (@ field_serde_name ; username) => { "username" } ; (@ field_serde_name ; avatar_url) => { "avatar_url" } ; } 396 | pub use _include_user as include; 397 | pub enum IncludeParam { 398 | Id(id::Include), 399 | Name(name::Include), 400 | Username(username::Include), 401 | AvatarUrl(avatar_url::Include), 402 | } 403 | impl IncludeParam { 404 | pub fn to_selection(self) -> ::prisma_client_rust::Selection { 405 | match self { 406 | Self::Id(data) => data.to_selection(), 407 | Self::Name(data) => data.to_selection(), 408 | Self::Username(data) => data.to_selection(), 409 | Self::AvatarUrl(data) => data.to_selection(), 410 | } 411 | } 412 | } 413 | #[derive(Debug, Clone, :: serde :: Serialize, :: serde :: Deserialize)] 414 | pub struct Data { 415 | #[serde(rename = "id")] 416 | pub id: i64, 417 | #[serde(rename = "name")] 418 | pub name: String, 419 | #[serde(rename = "username")] 420 | pub username: String, 421 | #[serde(rename = "avatar_url")] 422 | pub avatar_url: String, 423 | } 424 | impl Data {} 425 | #[derive(Clone)] 426 | pub enum WithParam {} 427 | impl Into<::prisma_client_rust::Selection> for WithParam { 428 | fn into(self) -> ::prisma_client_rust::Selection { 429 | match self {} 430 | } 431 | } 432 | #[derive(Clone)] 433 | pub enum SetParam { 434 | SetId(i64), 435 | IncrementId(i64), 436 | DecrementId(i64), 437 | MultiplyId(i64), 438 | DivideId(i64), 439 | SetName(String), 440 | SetUsername(String), 441 | SetAvatarUrl(String), 442 | } 443 | impl Into<(String, ::prisma_client_rust::PrismaValue)> for SetParam { 444 | fn into(self) -> (String, ::prisma_client_rust::PrismaValue) { 445 | match self { 446 | SetParam::SetId(value) => ( 447 | "id".to_string(), 448 | ::prisma_client_rust::PrismaValue::BigInt(value), 449 | ), 450 | SetParam::IncrementId(value) => ( 451 | "id".to_string(), 452 | ::prisma_client_rust::PrismaValue::Object(vec![( 453 | "increment".to_string(), 454 | ::prisma_client_rust::PrismaValue::BigInt(value), 455 | )]), 456 | ), 457 | SetParam::DecrementId(value) => ( 458 | "id".to_string(), 459 | ::prisma_client_rust::PrismaValue::Object(vec![( 460 | "decrement".to_string(), 461 | ::prisma_client_rust::PrismaValue::BigInt(value), 462 | )]), 463 | ), 464 | SetParam::MultiplyId(value) => ( 465 | "id".to_string(), 466 | ::prisma_client_rust::PrismaValue::Object(vec![( 467 | "multiply".to_string(), 468 | ::prisma_client_rust::PrismaValue::BigInt(value), 469 | )]), 470 | ), 471 | SetParam::DivideId(value) => ( 472 | "id".to_string(), 473 | ::prisma_client_rust::PrismaValue::Object(vec![( 474 | "divide".to_string(), 475 | ::prisma_client_rust::PrismaValue::BigInt(value), 476 | )]), 477 | ), 478 | SetParam::SetName(value) => ( 479 | "name".to_string(), 480 | ::prisma_client_rust::PrismaValue::String(value), 481 | ), 482 | SetParam::SetUsername(value) => ( 483 | "username".to_string(), 484 | ::prisma_client_rust::PrismaValue::String(value), 485 | ), 486 | SetParam::SetAvatarUrl(value) => ( 487 | "avatar_url".to_string(), 488 | ::prisma_client_rust::PrismaValue::String(value), 489 | ), 490 | } 491 | } 492 | } 493 | #[derive(Clone)] 494 | pub enum OrderByParam { 495 | Id(::prisma_client_rust::Direction), 496 | Name(::prisma_client_rust::Direction), 497 | Username(::prisma_client_rust::Direction), 498 | AvatarUrl(::prisma_client_rust::Direction), 499 | } 500 | impl Into<(String, ::prisma_client_rust::PrismaValue)> for OrderByParam { 501 | fn into(self) -> (String, ::prisma_client_rust::PrismaValue) { 502 | match self { 503 | Self::Id(direction) => ( 504 | "id".to_string(), 505 | ::prisma_client_rust::PrismaValue::String(direction.to_string()), 506 | ), 507 | Self::Name(direction) => ( 508 | "name".to_string(), 509 | ::prisma_client_rust::PrismaValue::String(direction.to_string()), 510 | ), 511 | Self::Username(direction) => ( 512 | "username".to_string(), 513 | ::prisma_client_rust::PrismaValue::String(direction.to_string()), 514 | ), 515 | Self::AvatarUrl(direction) => ( 516 | "avatar_url".to_string(), 517 | ::prisma_client_rust::PrismaValue::String(direction.to_string()), 518 | ), 519 | } 520 | } 521 | } 522 | #[derive(Clone)] 523 | pub enum WhereParam { 524 | Not(Vec), 525 | Or(Vec), 526 | And(Vec), 527 | IdEquals(i64), 528 | IdInVec(Vec), 529 | IdNotInVec(Vec), 530 | IdLt(i64), 531 | IdLte(i64), 532 | IdGt(i64), 533 | IdGte(i64), 534 | IdNot(i64), 535 | NameEquals(String), 536 | NameInVec(Vec), 537 | NameNotInVec(Vec), 538 | NameLt(String), 539 | NameLte(String), 540 | NameGt(String), 541 | NameGte(String), 542 | NameContains(String), 543 | NameStartsWith(String), 544 | NameEndsWith(String), 545 | NameMode(QueryMode), 546 | NameNot(String), 547 | UsernameEquals(String), 548 | UsernameInVec(Vec), 549 | UsernameNotInVec(Vec), 550 | UsernameLt(String), 551 | UsernameLte(String), 552 | UsernameGt(String), 553 | UsernameGte(String), 554 | UsernameContains(String), 555 | UsernameStartsWith(String), 556 | UsernameEndsWith(String), 557 | UsernameMode(QueryMode), 558 | UsernameNot(String), 559 | AvatarUrlEquals(String), 560 | AvatarUrlInVec(Vec), 561 | AvatarUrlNotInVec(Vec), 562 | AvatarUrlLt(String), 563 | AvatarUrlLte(String), 564 | AvatarUrlGt(String), 565 | AvatarUrlGte(String), 566 | AvatarUrlContains(String), 567 | AvatarUrlStartsWith(String), 568 | AvatarUrlEndsWith(String), 569 | AvatarUrlMode(QueryMode), 570 | AvatarUrlNot(String), 571 | } 572 | impl Into<::prisma_client_rust::SerializedWhere> for WhereParam { 573 | fn into(self) -> ::prisma_client_rust::SerializedWhere { 574 | match self { 575 | Self::Not(value) => ::prisma_client_rust::SerializedWhere::new( 576 | "NOT", 577 | ::prisma_client_rust::SerializedWhereValue::Object( 578 | value 579 | .into_iter() 580 | .map(Into::<::prisma_client_rust::SerializedWhere>::into) 581 | .map(Into::into) 582 | .collect(), 583 | ), 584 | ), 585 | Self::Or(value) => ::prisma_client_rust::SerializedWhere::new( 586 | "OR", 587 | ::prisma_client_rust::SerializedWhereValue::List( 588 | value 589 | .into_iter() 590 | .map(Into::<::prisma_client_rust::SerializedWhere>::into) 591 | .map(Into::into) 592 | .map(|v| vec![v]) 593 | .map(::prisma_client_rust::PrismaValue::Object) 594 | .collect(), 595 | ), 596 | ), 597 | Self::And(value) => ::prisma_client_rust::SerializedWhere::new( 598 | "AND", 599 | ::prisma_client_rust::SerializedWhereValue::Object( 600 | value 601 | .into_iter() 602 | .map(Into::<::prisma_client_rust::SerializedWhere>::into) 603 | .map(Into::into) 604 | .collect(), 605 | ), 606 | ), 607 | Self::IdEquals(value) => ::prisma_client_rust::SerializedWhere::new( 608 | "id", 609 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 610 | "equals".to_string(), 611 | ::prisma_client_rust::PrismaValue::BigInt(value), 612 | )]), 613 | ), 614 | Self::IdInVec(value) => ::prisma_client_rust::SerializedWhere::new( 615 | "id", 616 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 617 | "in".to_string(), 618 | ::prisma_client_rust::PrismaValue::List( 619 | value 620 | .into_iter() 621 | .map(|v| ::prisma_client_rust::PrismaValue::BigInt(v)) 622 | .collect(), 623 | ), 624 | )]), 625 | ), 626 | Self::IdNotInVec(value) => ::prisma_client_rust::SerializedWhere::new( 627 | "id", 628 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 629 | "notIn".to_string(), 630 | ::prisma_client_rust::PrismaValue::List( 631 | value 632 | .into_iter() 633 | .map(|v| ::prisma_client_rust::PrismaValue::BigInt(v)) 634 | .collect(), 635 | ), 636 | )]), 637 | ), 638 | Self::IdLt(value) => ::prisma_client_rust::SerializedWhere::new( 639 | "id", 640 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 641 | "lt".to_string(), 642 | ::prisma_client_rust::PrismaValue::BigInt(value), 643 | )]), 644 | ), 645 | Self::IdLte(value) => ::prisma_client_rust::SerializedWhere::new( 646 | "id", 647 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 648 | "lte".to_string(), 649 | ::prisma_client_rust::PrismaValue::BigInt(value), 650 | )]), 651 | ), 652 | Self::IdGt(value) => ::prisma_client_rust::SerializedWhere::new( 653 | "id", 654 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 655 | "gt".to_string(), 656 | ::prisma_client_rust::PrismaValue::BigInt(value), 657 | )]), 658 | ), 659 | Self::IdGte(value) => ::prisma_client_rust::SerializedWhere::new( 660 | "id", 661 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 662 | "gte".to_string(), 663 | ::prisma_client_rust::PrismaValue::BigInt(value), 664 | )]), 665 | ), 666 | Self::IdNot(value) => ::prisma_client_rust::SerializedWhere::new( 667 | "id", 668 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 669 | "not".to_string(), 670 | ::prisma_client_rust::PrismaValue::BigInt(value), 671 | )]), 672 | ), 673 | Self::NameEquals(value) => ::prisma_client_rust::SerializedWhere::new( 674 | "name", 675 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 676 | "equals".to_string(), 677 | ::prisma_client_rust::PrismaValue::String(value), 678 | )]), 679 | ), 680 | Self::NameInVec(value) => ::prisma_client_rust::SerializedWhere::new( 681 | "name", 682 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 683 | "in".to_string(), 684 | ::prisma_client_rust::PrismaValue::List( 685 | value 686 | .into_iter() 687 | .map(|v| ::prisma_client_rust::PrismaValue::String(v)) 688 | .collect(), 689 | ), 690 | )]), 691 | ), 692 | Self::NameNotInVec(value) => ::prisma_client_rust::SerializedWhere::new( 693 | "name", 694 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 695 | "notIn".to_string(), 696 | ::prisma_client_rust::PrismaValue::List( 697 | value 698 | .into_iter() 699 | .map(|v| ::prisma_client_rust::PrismaValue::String(v)) 700 | .collect(), 701 | ), 702 | )]), 703 | ), 704 | Self::NameLt(value) => ::prisma_client_rust::SerializedWhere::new( 705 | "name", 706 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 707 | "lt".to_string(), 708 | ::prisma_client_rust::PrismaValue::String(value), 709 | )]), 710 | ), 711 | Self::NameLte(value) => ::prisma_client_rust::SerializedWhere::new( 712 | "name", 713 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 714 | "lte".to_string(), 715 | ::prisma_client_rust::PrismaValue::String(value), 716 | )]), 717 | ), 718 | Self::NameGt(value) => ::prisma_client_rust::SerializedWhere::new( 719 | "name", 720 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 721 | "gt".to_string(), 722 | ::prisma_client_rust::PrismaValue::String(value), 723 | )]), 724 | ), 725 | Self::NameGte(value) => ::prisma_client_rust::SerializedWhere::new( 726 | "name", 727 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 728 | "gte".to_string(), 729 | ::prisma_client_rust::PrismaValue::String(value), 730 | )]), 731 | ), 732 | Self::NameContains(value) => ::prisma_client_rust::SerializedWhere::new( 733 | "name", 734 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 735 | "contains".to_string(), 736 | ::prisma_client_rust::PrismaValue::String(value), 737 | )]), 738 | ), 739 | Self::NameStartsWith(value) => ::prisma_client_rust::SerializedWhere::new( 740 | "name", 741 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 742 | "startsWith".to_string(), 743 | ::prisma_client_rust::PrismaValue::String(value), 744 | )]), 745 | ), 746 | Self::NameEndsWith(value) => ::prisma_client_rust::SerializedWhere::new( 747 | "name", 748 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 749 | "endsWith".to_string(), 750 | ::prisma_client_rust::PrismaValue::String(value), 751 | )]), 752 | ), 753 | Self::NameMode(value) => ::prisma_client_rust::SerializedWhere::new( 754 | "name", 755 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 756 | "mode".to_string(), 757 | ::prisma_client_rust::PrismaValue::Enum(value.to_string()), 758 | )]), 759 | ), 760 | Self::NameNot(value) => ::prisma_client_rust::SerializedWhere::new( 761 | "name", 762 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 763 | "not".to_string(), 764 | ::prisma_client_rust::PrismaValue::String(value), 765 | )]), 766 | ), 767 | Self::UsernameEquals(value) => ::prisma_client_rust::SerializedWhere::new( 768 | "username", 769 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 770 | "equals".to_string(), 771 | ::prisma_client_rust::PrismaValue::String(value), 772 | )]), 773 | ), 774 | Self::UsernameInVec(value) => ::prisma_client_rust::SerializedWhere::new( 775 | "username", 776 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 777 | "in".to_string(), 778 | ::prisma_client_rust::PrismaValue::List( 779 | value 780 | .into_iter() 781 | .map(|v| ::prisma_client_rust::PrismaValue::String(v)) 782 | .collect(), 783 | ), 784 | )]), 785 | ), 786 | Self::UsernameNotInVec(value) => ::prisma_client_rust::SerializedWhere::new( 787 | "username", 788 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 789 | "notIn".to_string(), 790 | ::prisma_client_rust::PrismaValue::List( 791 | value 792 | .into_iter() 793 | .map(|v| ::prisma_client_rust::PrismaValue::String(v)) 794 | .collect(), 795 | ), 796 | )]), 797 | ), 798 | Self::UsernameLt(value) => ::prisma_client_rust::SerializedWhere::new( 799 | "username", 800 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 801 | "lt".to_string(), 802 | ::prisma_client_rust::PrismaValue::String(value), 803 | )]), 804 | ), 805 | Self::UsernameLte(value) => ::prisma_client_rust::SerializedWhere::new( 806 | "username", 807 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 808 | "lte".to_string(), 809 | ::prisma_client_rust::PrismaValue::String(value), 810 | )]), 811 | ), 812 | Self::UsernameGt(value) => ::prisma_client_rust::SerializedWhere::new( 813 | "username", 814 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 815 | "gt".to_string(), 816 | ::prisma_client_rust::PrismaValue::String(value), 817 | )]), 818 | ), 819 | Self::UsernameGte(value) => ::prisma_client_rust::SerializedWhere::new( 820 | "username", 821 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 822 | "gte".to_string(), 823 | ::prisma_client_rust::PrismaValue::String(value), 824 | )]), 825 | ), 826 | Self::UsernameContains(value) => ::prisma_client_rust::SerializedWhere::new( 827 | "username", 828 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 829 | "contains".to_string(), 830 | ::prisma_client_rust::PrismaValue::String(value), 831 | )]), 832 | ), 833 | Self::UsernameStartsWith(value) => ::prisma_client_rust::SerializedWhere::new( 834 | "username", 835 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 836 | "startsWith".to_string(), 837 | ::prisma_client_rust::PrismaValue::String(value), 838 | )]), 839 | ), 840 | Self::UsernameEndsWith(value) => ::prisma_client_rust::SerializedWhere::new( 841 | "username", 842 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 843 | "endsWith".to_string(), 844 | ::prisma_client_rust::PrismaValue::String(value), 845 | )]), 846 | ), 847 | Self::UsernameMode(value) => ::prisma_client_rust::SerializedWhere::new( 848 | "username", 849 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 850 | "mode".to_string(), 851 | ::prisma_client_rust::PrismaValue::Enum(value.to_string()), 852 | )]), 853 | ), 854 | Self::UsernameNot(value) => ::prisma_client_rust::SerializedWhere::new( 855 | "username", 856 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 857 | "not".to_string(), 858 | ::prisma_client_rust::PrismaValue::String(value), 859 | )]), 860 | ), 861 | Self::AvatarUrlEquals(value) => ::prisma_client_rust::SerializedWhere::new( 862 | "avatar_url", 863 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 864 | "equals".to_string(), 865 | ::prisma_client_rust::PrismaValue::String(value), 866 | )]), 867 | ), 868 | Self::AvatarUrlInVec(value) => ::prisma_client_rust::SerializedWhere::new( 869 | "avatar_url", 870 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 871 | "in".to_string(), 872 | ::prisma_client_rust::PrismaValue::List( 873 | value 874 | .into_iter() 875 | .map(|v| ::prisma_client_rust::PrismaValue::String(v)) 876 | .collect(), 877 | ), 878 | )]), 879 | ), 880 | Self::AvatarUrlNotInVec(value) => ::prisma_client_rust::SerializedWhere::new( 881 | "avatar_url", 882 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 883 | "notIn".to_string(), 884 | ::prisma_client_rust::PrismaValue::List( 885 | value 886 | .into_iter() 887 | .map(|v| ::prisma_client_rust::PrismaValue::String(v)) 888 | .collect(), 889 | ), 890 | )]), 891 | ), 892 | Self::AvatarUrlLt(value) => ::prisma_client_rust::SerializedWhere::new( 893 | "avatar_url", 894 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 895 | "lt".to_string(), 896 | ::prisma_client_rust::PrismaValue::String(value), 897 | )]), 898 | ), 899 | Self::AvatarUrlLte(value) => ::prisma_client_rust::SerializedWhere::new( 900 | "avatar_url", 901 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 902 | "lte".to_string(), 903 | ::prisma_client_rust::PrismaValue::String(value), 904 | )]), 905 | ), 906 | Self::AvatarUrlGt(value) => ::prisma_client_rust::SerializedWhere::new( 907 | "avatar_url", 908 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 909 | "gt".to_string(), 910 | ::prisma_client_rust::PrismaValue::String(value), 911 | )]), 912 | ), 913 | Self::AvatarUrlGte(value) => ::prisma_client_rust::SerializedWhere::new( 914 | "avatar_url", 915 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 916 | "gte".to_string(), 917 | ::prisma_client_rust::PrismaValue::String(value), 918 | )]), 919 | ), 920 | Self::AvatarUrlContains(value) => ::prisma_client_rust::SerializedWhere::new( 921 | "avatar_url", 922 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 923 | "contains".to_string(), 924 | ::prisma_client_rust::PrismaValue::String(value), 925 | )]), 926 | ), 927 | Self::AvatarUrlStartsWith(value) => ::prisma_client_rust::SerializedWhere::new( 928 | "avatar_url", 929 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 930 | "startsWith".to_string(), 931 | ::prisma_client_rust::PrismaValue::String(value), 932 | )]), 933 | ), 934 | Self::AvatarUrlEndsWith(value) => ::prisma_client_rust::SerializedWhere::new( 935 | "avatar_url", 936 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 937 | "endsWith".to_string(), 938 | ::prisma_client_rust::PrismaValue::String(value), 939 | )]), 940 | ), 941 | Self::AvatarUrlMode(value) => ::prisma_client_rust::SerializedWhere::new( 942 | "avatar_url", 943 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 944 | "mode".to_string(), 945 | ::prisma_client_rust::PrismaValue::Enum(value.to_string()), 946 | )]), 947 | ), 948 | Self::AvatarUrlNot(value) => ::prisma_client_rust::SerializedWhere::new( 949 | "avatar_url", 950 | ::prisma_client_rust::SerializedWhereValue::Object(vec![( 951 | "not".to_string(), 952 | ::prisma_client_rust::PrismaValue::String(value), 953 | )]), 954 | ), 955 | } 956 | } 957 | } 958 | #[derive(Clone)] 959 | pub enum UniqueWhereParam { 960 | IdEquals(i64), 961 | } 962 | impl From for WhereParam { 963 | fn from(value: UniqueWhereParam) -> Self { 964 | match value { 965 | UniqueWhereParam::IdEquals(value) => Self::IdEquals(value), 966 | } 967 | } 968 | } 969 | impl From<::prisma_client_rust::Operator> for WhereParam { 970 | fn from(op: ::prisma_client_rust::Operator) -> Self { 971 | match op { 972 | ::prisma_client_rust::Operator::Not(value) => Self::Not(value), 973 | ::prisma_client_rust::Operator::And(value) => Self::And(value), 974 | ::prisma_client_rust::Operator::Or(value) => Self::Or(value), 975 | } 976 | } 977 | } 978 | pub type UniqueArgs = ::prisma_client_rust::UniqueArgs; 979 | pub type ManyArgs = 980 | ::prisma_client_rust::ManyArgs; 981 | pub type Count<'a> = 982 | ::prisma_client_rust::Count<'a, WhereParam, OrderByParam, UniqueWhereParam>; 983 | pub type Create<'a> = ::prisma_client_rust::Create<'a, SetParam, WithParam, Data>; 984 | pub type CreateMany<'a> = ::prisma_client_rust::CreateMany<'a, SetParam>; 985 | pub type FindUnique<'a> = 986 | ::prisma_client_rust::FindUnique<'a, WhereParam, WithParam, SetParam, Data>; 987 | pub type FindMany<'a> = ::prisma_client_rust::FindMany< 988 | 'a, 989 | WhereParam, 990 | WithParam, 991 | OrderByParam, 992 | UniqueWhereParam, 993 | SetParam, 994 | Data, 995 | >; 996 | pub type FindFirst<'a> = ::prisma_client_rust::FindFirst< 997 | 'a, 998 | WhereParam, 999 | WithParam, 1000 | OrderByParam, 1001 | UniqueWhereParam, 1002 | Data, 1003 | >; 1004 | pub type Update<'a> = ::prisma_client_rust::Update<'a, WhereParam, WithParam, SetParam, Data>; 1005 | pub type UpdateMany<'a> = ::prisma_client_rust::UpdateMany<'a, WhereParam, SetParam>; 1006 | pub type Upsert<'a> = ::prisma_client_rust::Upsert<'a, WhereParam, SetParam, WithParam, Data>; 1007 | pub type Delete<'a> = ::prisma_client_rust::Delete<'a, WhereParam, WithParam, Data>; 1008 | pub type DeleteMany<'a> = ::prisma_client_rust::DeleteMany<'a, WhereParam>; 1009 | pub struct Actions<'a> { 1010 | pub client: &'a PrismaClient, 1011 | } 1012 | impl<'a> Actions<'a> { 1013 | pub fn find_unique(self, _where: UniqueWhereParam) -> FindUnique<'a> { 1014 | FindUnique::new( 1015 | self.client._new_query_context(), 1016 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1017 | _where.into(), 1018 | ) 1019 | } 1020 | pub fn find_first(self, _where: Vec) -> FindFirst<'a> { 1021 | FindFirst::new( 1022 | self.client._new_query_context(), 1023 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1024 | _where, 1025 | ) 1026 | } 1027 | pub fn find_many(self, _where: Vec) -> FindMany<'a> { 1028 | FindMany::new( 1029 | self.client._new_query_context(), 1030 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1031 | _where, 1032 | ) 1033 | } 1034 | pub fn create( 1035 | self, 1036 | id: i64, 1037 | name: String, 1038 | username: String, 1039 | avatar_url: String, 1040 | mut _params: Vec, 1041 | ) -> Create<'a> { 1042 | _params.push(id::set(id)); 1043 | _params.push(name::set(name)); 1044 | _params.push(username::set(username)); 1045 | _params.push(avatar_url::set(avatar_url)); 1046 | Create::new( 1047 | self.client._new_query_context(), 1048 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1049 | _params, 1050 | ) 1051 | } 1052 | pub fn create_many( 1053 | self, 1054 | data: Vec<(i64, String, String, String, Vec)>, 1055 | ) -> CreateMany<'a> { 1056 | let data = data 1057 | .into_iter() 1058 | .map(|(id, name, username, avatar_url, mut _params)| { 1059 | _params.push(id::set(id)); 1060 | _params.push(name::set(name)); 1061 | _params.push(username::set(username)); 1062 | _params.push(avatar_url::set(avatar_url)); 1063 | _params 1064 | }) 1065 | .collect(); 1066 | CreateMany::new( 1067 | self.client._new_query_context(), 1068 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1069 | data, 1070 | ) 1071 | } 1072 | pub fn update(self, _where: UniqueWhereParam, _params: Vec) -> Update<'a> { 1073 | Update::new( 1074 | self.client._new_query_context(), 1075 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1076 | _where.into(), 1077 | _params, 1078 | vec![], 1079 | ) 1080 | } 1081 | pub fn update_many( 1082 | self, 1083 | _where: Vec, 1084 | _params: Vec, 1085 | ) -> UpdateMany<'a> { 1086 | UpdateMany::new( 1087 | self.client._new_query_context(), 1088 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1089 | _where, 1090 | _params, 1091 | ) 1092 | } 1093 | pub fn upsert( 1094 | self, 1095 | _where: UniqueWhereParam, 1096 | (id, name, username, avatar_url, mut _params): ( 1097 | i64, 1098 | String, 1099 | String, 1100 | String, 1101 | Vec, 1102 | ), 1103 | _update: Vec, 1104 | ) -> Upsert<'a> { 1105 | _params.push(id::set(id)); 1106 | _params.push(name::set(name)); 1107 | _params.push(username::set(username)); 1108 | _params.push(avatar_url::set(avatar_url)); 1109 | Upsert::new( 1110 | self.client._new_query_context(), 1111 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1112 | _where.into(), 1113 | _params, 1114 | _update, 1115 | ) 1116 | } 1117 | pub fn delete(self, _where: UniqueWhereParam) -> Delete<'a> { 1118 | Delete::new( 1119 | self.client._new_query_context(), 1120 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1121 | _where.into(), 1122 | vec![], 1123 | ) 1124 | } 1125 | pub fn delete_many(self, _where: Vec) -> DeleteMany<'a> { 1126 | DeleteMany::new( 1127 | self.client._new_query_context(), 1128 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1129 | _where.into(), 1130 | ) 1131 | } 1132 | pub fn count(self, _where: Vec) -> Count<'a> { 1133 | Count::new( 1134 | self.client._new_query_context(), 1135 | ::prisma_client_rust::QueryInfo::new("User", _outputs()), 1136 | vec![], 1137 | ) 1138 | } 1139 | } 1140 | } 1141 | pub mod _prisma { 1142 | pub struct PrismaClient { 1143 | executor: ::prisma_client_rust::Executor, 1144 | query_schema: ::std::sync::Arc<::prisma_client_rust::schema::QuerySchema>, 1145 | } 1146 | impl ::std::fmt::Debug for PrismaClient { 1147 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 1148 | f.debug_struct("PrismaClient").finish() 1149 | } 1150 | } 1151 | impl PrismaClient { 1152 | pub(super) fn _new_query_context(&self) -> ::prisma_client_rust::queries::QueryContext { 1153 | ::prisma_client_rust::queries::QueryContext::new(&self.executor, &self.query_schema) 1154 | } 1155 | pub(super) fn _new( 1156 | executor: ::prisma_client_rust::Executor, 1157 | query_schema: std::sync::Arc<::prisma_client_rust::schema::QuerySchema>, 1158 | ) -> Self { 1159 | Self { 1160 | executor, 1161 | query_schema, 1162 | } 1163 | } 1164 | pub fn _query_raw( 1165 | &self, 1166 | query: ::prisma_client_rust::raw::Raw, 1167 | ) -> ::prisma_client_rust::QueryRaw { 1168 | ::prisma_client_rust::QueryRaw::new( 1169 | ::prisma_client_rust::queries::QueryContext::new( 1170 | &self.executor, 1171 | &self.query_schema, 1172 | ), 1173 | query, 1174 | super::DATABASE_STR, 1175 | ) 1176 | } 1177 | pub fn _execute_raw( 1178 | &self, 1179 | query: ::prisma_client_rust::raw::Raw, 1180 | ) -> ::prisma_client_rust::ExecuteRaw { 1181 | ::prisma_client_rust::ExecuteRaw::new( 1182 | ::prisma_client_rust::queries::QueryContext::new( 1183 | &self.executor, 1184 | &self.query_schema, 1185 | ), 1186 | query, 1187 | super::DATABASE_STR, 1188 | ) 1189 | } 1190 | pub async fn _batch, Marker>( 1191 | &self, 1192 | queries: T, 1193 | ) -> ::prisma_client_rust::queries::Result { 1194 | ::prisma_client_rust::batch(queries, &self.executor, &self.query_schema).await 1195 | } 1196 | pub fn user(&self) -> super::user::Actions { 1197 | super::user::Actions { client: &self } 1198 | } 1199 | } 1200 | #[derive(Debug, Clone, Copy, :: serde :: Serialize, :: serde :: Deserialize)] 1201 | pub enum QueryMode { 1202 | #[serde(rename = "default")] 1203 | Default, 1204 | #[serde(rename = "insensitive")] 1205 | Insensitive, 1206 | } 1207 | impl ToString for QueryMode { 1208 | fn to_string(&self) -> String { 1209 | match self { 1210 | Self::Default => "default".to_string(), 1211 | Self::Insensitive => "insensitive".to_string(), 1212 | } 1213 | } 1214 | } 1215 | #[derive(Debug, Clone, Copy, :: serde :: Serialize, :: serde :: Deserialize)] 1216 | pub enum SortOrder { 1217 | #[serde(rename = "asc")] 1218 | Asc, 1219 | #[serde(rename = "desc")] 1220 | Desc, 1221 | } 1222 | impl ToString for SortOrder { 1223 | fn to_string(&self) -> String { 1224 | match self { 1225 | Self::Asc => "asc".to_string(), 1226 | Self::Desc => "desc".to_string(), 1227 | } 1228 | } 1229 | } 1230 | #[derive(Debug, Clone, Copy, :: serde :: Serialize, :: serde :: Deserialize)] 1231 | pub enum TransactionIsolationLevel { 1232 | #[serde(rename = "ReadUncommitted")] 1233 | ReadUncommitted, 1234 | #[serde(rename = "ReadCommitted")] 1235 | ReadCommitted, 1236 | #[serde(rename = "RepeatableRead")] 1237 | RepeatableRead, 1238 | #[serde(rename = "Serializable")] 1239 | Serializable, 1240 | } 1241 | impl ToString for TransactionIsolationLevel { 1242 | fn to_string(&self) -> String { 1243 | match self { 1244 | Self::ReadUncommitted => "ReadUncommitted".to_string(), 1245 | Self::ReadCommitted => "ReadCommitted".to_string(), 1246 | Self::RepeatableRead => "RepeatableRead".to_string(), 1247 | Self::Serializable => "Serializable".to_string(), 1248 | } 1249 | } 1250 | } 1251 | #[derive(Debug, Clone, Copy, :: serde :: Serialize, :: serde :: Deserialize)] 1252 | pub enum UserScalarFieldEnum { 1253 | #[serde(rename = "id")] 1254 | Id, 1255 | #[serde(rename = "name")] 1256 | Name, 1257 | #[serde(rename = "username")] 1258 | Username, 1259 | #[serde(rename = "avatar_url")] 1260 | AvatarUrl, 1261 | } 1262 | impl ToString for UserScalarFieldEnum { 1263 | fn to_string(&self) -> String { 1264 | match self { 1265 | Self::Id => "id".to_string(), 1266 | Self::Name => "name".to_string(), 1267 | Self::Username => "username".to_string(), 1268 | Self::AvatarUrl => "avatar_url".to_string(), 1269 | } 1270 | } 1271 | } 1272 | } 1273 | pub use _prisma::PrismaClient; 1274 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use rocket::serde::{Serialize, Deserialize}; 2 | 3 | #[derive(Deserialize, Serialize)] 4 | #[serde(crate = "rocket::serde")] 5 | pub enum ErrorKind { 6 | NotLoggedIn, 7 | ValidationError, 8 | GithubApiError, 9 | DatabaseError(String) 10 | } 11 | #[derive(Deserialize, Serialize)] 12 | #[serde(crate = "rocket::serde")] 13 | pub struct Error { 14 | pub(crate) kind: ErrorKind, 15 | pub(crate) action: String, 16 | pub(crate) message: String 17 | } -------------------------------------------------------------------------------- /src/github.rs: -------------------------------------------------------------------------------- 1 | use rocket::http::{CookieJar, Status}; 2 | use rocket::response::Redirect; 3 | use rocket::serde::json::Json; 4 | use rocket_oauth2::{OAuth2, TokenResponse}; 5 | use octorust::Client; 6 | use octorust::auth::Credentials; 7 | use rocket::response::status; 8 | use crate::{Session, SessionInfo}; 9 | use crate::db::*; 10 | use crate::error::*; 11 | pub struct GitHub; 12 | 13 | #[get("/login/github")] 14 | pub fn github_login(oauth2: OAuth2, cookies: &CookieJar<'_>) -> Redirect { 15 | oauth2.get_redirect(cookies, &["read:user"]).unwrap() 16 | } 17 | 18 | #[get("/auth/github")] 19 | pub async fn github_callback(token: TokenResponse, session: Session<'_>) -> Result>> 20 | { 21 | let gh_token =token.access_token().to_string(); 22 | let github = Client::new("LapceExtensions", Credentials::Token(gh_token.clone().into())); 23 | match github { 24 | Ok(github) => { 25 | let users = github.users(); 26 | let user = users.get_authenticated().await.unwrap(); 27 | let user = user.public_user().unwrap(); 28 | if let Err(err) = session.set(SessionInfo { 29 | gh_token, 30 | id: user.id as u64 31 | }).await { 32 | Err(status::Custom(Status::InternalServerError, Json(Error { 33 | kind: ErrorKind::DatabaseError(err.to_string()), 34 | action: "Try again".into(), 35 | message: "Can't set session on redis db".into() 36 | }))) 37 | } else { 38 | let client = establish_connection().await; 39 | match client { 40 | Ok(client) => { 41 | client.user().upsert( 42 | prisma::user::id::equals(user.id), 43 | prisma::user::create( 44 | user.id, 45 | user.login.clone(), 46 | user.name.clone(), 47 | user.avatar_url.clone(), 48 | vec![] 49 | ), 50 | vec![ 51 | prisma::user::name::set(user.login.clone()), 52 | prisma::user::username::set(user.name.clone()), 53 | prisma::user::avatar_url::set(user.avatar_url.clone()), 54 | ] 55 | ).exec().await.unwrap(); 56 | Ok(Redirect::to("/")) 57 | } 58 | Err(err) => { 59 | Err(status::Custom(Status::InternalServerError, Json(err))) 60 | } 61 | } 62 | } 63 | } 64 | Err(_) => Err(status::Custom(Status::InternalServerError, Json(Error { 65 | kind: ErrorKind::GithubApiError, 66 | action: "Try again".into(), 67 | message: "Can't fetch from github api".into() 68 | }))) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | pub mod user; 3 | mod github; 4 | pub mod db; 5 | pub mod error; 6 | use std::time::Duration; 7 | use dotenvy::dotenv; 8 | use redis::Client; 9 | use rocket::fairing::AdHoc; 10 | use rocket::fs::FileServer; 11 | use rocket::serde::{Deserialize, Serialize}; 12 | use rocket_oauth2::{OAuth2, HyperRustlsAdapter, StaticProvider, OAuthConfig}; 13 | pub use rocket_session_store::{redis::*, SessionStore, CookieConfig}; 14 | use crate::github::*; 15 | use crate::user::get_user; 16 | #[derive(Serialize, Deserialize, Clone, Debug)] 17 | #[serde(crate = "rocket::serde")] 18 | pub struct SessionInfo { 19 | pub id: u64, 20 | pub gh_token: String 21 | } 22 | pub type Session<'s> = rocket_session_store::Session<'s, SessionInfo>; 23 | #[launch] 24 | fn rocket() -> _ { 25 | dotenv().ok(); 26 | let client: Client = Client::open(std::env::var("REDIS_URL").unwrap_or("redis://localhost".into())) 27 | .expect("Failed to connect to redis"); 28 | let redis_store: RedisStore = RedisStore::new(client); 29 | let store: SessionStore = SessionStore { 30 | store: Box::new(redis_store), 31 | name: "token".into(), 32 | 33 | duration: Duration::from_secs(3600 * 24 * 3), 34 | cookie: CookieConfig { 35 | http_only: false, 36 | secure: true, 37 | path: Some("/".into()), 38 | ..Default::default() 39 | }, 40 | }; 41 | rocket::build() 42 | .mount("/", routes![github_callback, github_login]) 43 | .mount("/api/", routes![get_user, crate::user::logout]) 44 | .attach(AdHoc::on_ignite("GitHub OAuth Config", |rocket| async { 45 | let config = OAuthConfig::new( 46 | StaticProvider::GitHub, 47 | std::env::var("GH_CLIENT_ID").unwrap(), 48 | std::env::var("GH_CLIENT_SECRET").unwrap(), 49 | Some(std::env::var("GH_REDIRECT_URL").unwrap_or("https://localhost:8000/auth/github".into())), 50 | ); 51 | rocket.attach(OAuth2::::custom(HyperRustlsAdapter::default(), config)) 52 | })) 53 | .attach(store.fairing()) 54 | .mount("/", FileServer::from("marketplace/dist")) 55 | } 56 | -------------------------------------------------------------------------------- /src/user.rs: -------------------------------------------------------------------------------- 1 | 2 | use rocket::response::status::Unauthorized; 3 | use rocket::serde::json::Json; 4 | use crate::Session; 5 | use crate::db::{establish_connection, prisma::user}; 6 | use crate::error::*; 7 | 8 | #[get("/user")] 9 | pub async fn get_user(session: Session<'_>) -> Result, Unauthorized>>{ 10 | match session.get().await { 11 | Ok(Some(session)) => { 12 | let client = establish_connection().await; 13 | match client { 14 | Ok(client) => { 15 | let user = client.user().find_unique(user::id::equals(session.id as i64)).exec().await.ok(); 16 | if let Some(Some(user)) = user { 17 | Ok(Json(user)) 18 | } else { 19 | Err(Unauthorized(Some(Json(Error { 20 | kind: ErrorKind::NotLoggedIn, 21 | action: "Send a `token` cookie.".into(), 22 | message: "Unauthorized".into() 23 | })))) 24 | } 25 | } 26 | Err(err) => { 27 | Err(Unauthorized(Some(Json(err)))) 28 | } 29 | } 30 | } 31 | _ => { 32 | Err(Unauthorized(Some(Json(Error { 33 | kind: ErrorKind::NotLoggedIn, 34 | action: "Send a `token` cookie.".into(), 35 | message: "Unauthorized".into() 36 | })))) 37 | } 38 | } 39 | 40 | 41 | } 42 | #[delete("/session")] 43 | pub async fn logout(session: Session<'_>) -> Result<(), Unauthorized>> { 44 | if let None = session.get().await.unwrap(){ 45 | Err(Unauthorized(Some(Json(Error { 46 | kind: ErrorKind::NotLoggedIn, 47 | action: "Send a `token` cookie.".into(), 48 | message: "You're already logged out".into() 49 | })))) 50 | } else { 51 | session.remove().await.unwrap(); 52 | Ok(()) 53 | } 54 | } --------------------------------------------------------------------------------