From 31b1a46e79f876f4bfc58064bc596b752f275655 Mon Sep 17 00:00:00 2001 From: Jacob Sapoznikow <500074@bsd48.org> Date: Mon, 6 Nov 2023 01:35:52 +0000 Subject: [PATCH] New goals! --- .eslintrc.cjs | 60 ++++----- .github/workflows/codeql.yml | 80 ++++++------ .github/workflows/devskim.yml | 58 ++++----- .github/workflows/eslint.yml | 80 ++++++------ .github/workflows/rust-clippy.yml | 89 +++++++------ .github/workflows/tauri-linux.yml | 202 +++++++++++++++--------------- .github/workflows/tauri-mac.yml | 84 ++++++------- .github/workflows/tauri-win.yml | 84 ++++++------- .gitpod.yml | 3 + .prettierrc | 30 ++--- .stylelintrc.json | 36 +++--- README.md | 61 +++++---- cli/src/cli.rs | 150 +++++++++++----------- cli/src/commands/ckan/mod.rs | 194 ++++++++++++++-------------- cli/src/main.rs | 126 +++++++++---------- gui/tauri.conf.json | 150 +++++++++++----------- package.json | 188 +++++++++++++-------------- scripts/console.ts | 90 ++++++------- src/api/SpaceDock.ts | 94 +++++++------- src/api/boot.ts | 26 ++-- src/api/browse.ts | 26 ++-- src/api/dev.ts | 192 ++++++++++++++-------------- src/api/dropdown.ts | 8 +- src/api/instance.ts | 76 +++++------ src/api/invoke.ts | 188 +++++++++++++-------------- src/api/listen.ts | 62 ++++----- src/api/mocks/download.ts | 124 +++++++++--------- src/api/mocks/spaceDock.ts | 26 ++-- src/api/models/browse.ts | 34 ++--- src/api/models/modinfo/browse.ts | 104 +++++++-------- src/api/models/modinfo/full.ts | 98 +++++++-------- src/api/models/versions.ts | 42 +++---- src/api/setup.ts | 30 ++--- src/app.d.ts | 20 +-- src/app.html | 28 ++--- src/routes/+layout.ts | 2 +- src/styles/_includes.scss | 28 ++--- src/styles/global.scss | 58 ++++----- src/vite-env.d.ts | 4 +- svelte.config.js | 30 ++--- tsconfig.json | 58 ++++----- vite.config.ts | 92 +++++++------- 42 files changed, 1620 insertions(+), 1595 deletions(-) create mode 100644 .gitpod.yml diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 9f139c4..2896ee1 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,30 +1,30 @@ -module.exports = { - env: { - browser: true, - es2017: true, - node: true, - }, - - extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - - parser: "@typescript-eslint/parser", - plugins: ["svelte3", "@typescript-eslint"], - ignorePatterns: ["*.cjs"], - overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }], - - settings: { - "svelte3/typescript": () => require("typescript"), - }, - - parserOptions: { - ecmaVersion: 2020, - sourceType: "module", - }, - - rules: { - "no-case-declarations": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/triple-slash-reference": "off", - "@typescript-eslint/no-non-null-assertion": "off", - }, -}; +module.exports = { + env: { + browser: true, + es2017: true, + node: true, + }, + + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + + parser: "@typescript-eslint/parser", + plugins: ["svelte3", "@typescript-eslint"], + ignorePatterns: ["*.cjs"], + overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }], + + settings: { + "svelte3/typescript": () => require("typescript"), + }, + + parserOptions: { + ecmaVersion: 2020, + sourceType: "module", + }, + + rules: { + "no-case-declarations": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/triple-slash-reference": "off", + "@typescript-eslint/no-non-null-assertion": "off", + }, +}; diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1fd9262..68f78f2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,40 +1,40 @@ -name: "CodeQL" - -on: - push: - branches: ["main"] - pull_request: - branches: ["main"] - schedule: - - cron: "21 16 * * 6" - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ["javascript"] - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" +name: "CodeQL" + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + schedule: + - cron: "21 16 * * 6" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ["javascript"] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/devskim.yml b/.github/workflows/devskim.yml index ff3a9d5..f246356 100644 --- a/.github/workflows/devskim.yml +++ b/.github/workflows/devskim.yml @@ -1,29 +1,29 @@ -name: DevSkim - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - schedule: - - cron: '43 6 * * 5' - -jobs: - lint: - name: DevSkim - runs-on: ubuntu-20.04 - permissions: - actions: read - contents: read - security-events: write - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Run DevSkim scanner - uses: microsoft/DevSkim-Action@v1 - - - name: Upload DevSkim scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: devskim-results.sarif +name: DevSkim + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + schedule: + - cron: "43 6 * * 5" + +jobs: + lint: + name: DevSkim + runs-on: ubuntu-20.04 + permissions: + actions: read + contents: read + security-events: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Run DevSkim scanner + uses: microsoft/DevSkim-Action@v1 + + - name: Upload DevSkim scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: devskim-results.sarif diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index abcf8a2..18a98a5 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -1,40 +1,40 @@ -name: ESLint - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - schedule: - - cron: '23 17 * * 0' - -jobs: - eslint: - name: Run eslint scanning - runs-on: ubuntu-latest - permissions: - contents: read - security-events: write - actions: read - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Install ESLint - run: | - npm install eslint@8.10.0 - npm install @microsoft/eslint-formatter-sarif@2.1.7 - - - name: Run ESLint - run: npx eslint . - --config .eslintrc.cjs - --ext .js,.jsx,.ts,.tsx,.svelte - --format @microsoft/eslint-formatter-sarif - --output-file eslint-results.sarif - continue-on-error: true - - - name: Upload analysis results to GitHub - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: eslint-results.sarif - wait-for-processing: true +name: ESLint + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + schedule: + - cron: "23 17 * * 0" + +jobs: + eslint: + name: Run eslint scanning + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install ESLint + run: | + npm install eslint@8.10.0 + npm install @microsoft/eslint-formatter-sarif@2.1.7 + + - name: Run ESLint + run: npx eslint . + --config .eslintrc.cjs + --ext .js,.jsx,.ts,.tsx,.svelte + --format @microsoft/eslint-formatter-sarif + --output-file eslint-results.sarif + continue-on-error: true + + - name: Upload analysis results to GitHub + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: eslint-results.sarif + wait-for-processing: true diff --git a/.github/workflows/rust-clippy.yml b/.github/workflows/rust-clippy.yml index afa5e5d..7148d36 100644 --- a/.github/workflows/rust-clippy.yml +++ b/.github/workflows/rust-clippy.yml @@ -1,45 +1,44 @@ -name: rust-clippy analyze - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - schedule: - - cron: '40 23 * * 6' - -jobs: - rust-clippy-analyze: - name: Run rust-clippy analyzing - runs-on: ubuntu-latest - permissions: - contents: read - security-events: write - actions: read - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install Rust toolchain - uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af - with: - profile: minimal - toolchain: stable - components: clippy - override: true - - - name: Install required cargo - run: cargo install clippy-sarif sarif-fmt - - - name: Run rust-clippy - run: - cargo clippy - --all-features - --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt - continue-on-error: true - - - name: Upload analysis results to GitHub - uses: github/codeql-action/upload-sarif@v1 - with: - sarif_file: rust-clippy-results.sarif - wait-for-processing: true +name: rust-clippy analyze + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + schedule: + - cron: "40 23 * * 6" + +jobs: + rust-clippy-analyze: + name: Run rust-clippy analyzing + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af + with: + profile: minimal + toolchain: stable + components: clippy + override: true + + - name: Install required cargo + run: cargo install clippy-sarif sarif-fmt + + - name: Run rust-clippy + run: cargo clippy + --all-features + --message-format=json | clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt + continue-on-error: true + + - name: Upload analysis results to GitHub + uses: github/codeql-action/upload-sarif@v1 + with: + sarif_file: rust-clippy-results.sarif + wait-for-processing: true diff --git a/.github/workflows/tauri-linux.yml b/.github/workflows/tauri-linux.yml index 67892be..2244f85 100644 --- a/.github/workflows/tauri-linux.yml +++ b/.github/workflows/tauri-linux.yml @@ -1,101 +1,101 @@ -name: Publish (Linux) -on: [push] - -jobs: - publish-tauri-amd64: - permissions: - contents: write - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: setup node - uses: actions/setup-node@v3 - with: - node-version: 16 - - - name: install Rust nightly - uses: dtolnay/rust-toolchain@nightly - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf - - - name: Install pnpm - run: npm i -g pnpm - - - name: Install frontend dependencies - run: pnpm install - - - uses: benjlevesque/short-sha@v2.1 - id: short-sha - with: - length: 7 - - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} - releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" - releaseBody: | - "${{ github.event.head_commit.message }}" - See the assets to download this version and install. - releaseDraft: false - prerelease: true - tauriScript: pnpm tauri - - # publish-tauri-arm64: - # permissions: - # contents: write - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v3 - - # - name: setup node - # uses: actions/setup-node@v3 - # with: - # node-version: 16 - - # - name: install Rust nightly - # uses: dtolnay/rust-toolchain@nightly - # with: - # targets: aarch64-unknown-linux-gnu - - # - name: Install system dependencies - # run: | - # sudo apt-get update - # sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev \ - # libappindicator3-dev librsvg2-dev patchelf gcc-aarch64-linux-gnu \ - # g++-aarch64-linux-gnu - - # - name: Install pnpm - # run: npm i -g pnpm - - # - name: Install frontend dependencies - # run: pnpm install - - # - uses: benjlevesque/short-sha@v2.1 - # id: short-sha - # with: - # length: 7 - - # - name: Install cross - # run: | - # cargo install cross - - # - uses: tauri-apps/tauri-action@v0 - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # PKG_CONFIG_ALLOW_CROSS: 1 - # with: - # tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} - # releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" - # releaseBody: | - # "${{ github.event.head_commit.message }}" - # See the assets to download this version and install. - # releaseDraft: false - # prerelease: true - # tauriScript: pnpm tauri - # args: --target aarch64-unknown-linux-gnu --runner cross +name: Publish (Linux) +on: [push] + +jobs: + publish-tauri-amd64: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: install Rust nightly + uses: dtolnay/rust-toolchain@nightly + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + + - name: Install pnpm + run: npm i -g pnpm + + - name: Install frontend dependencies + run: pnpm install + + - uses: benjlevesque/short-sha@v2.1 + id: short-sha + with: + length: 7 + + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} + releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" + releaseBody: | + "${{ github.event.head_commit.message }}" + See the assets to download this version and install. + releaseDraft: false + prerelease: true + tauriScript: pnpm tauri + + # publish-tauri-arm64: + # permissions: + # contents: write + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v3 + + # - name: setup node + # uses: actions/setup-node@v3 + # with: + # node-version: 16 + + # - name: install Rust nightly + # uses: dtolnay/rust-toolchain@nightly + # with: + # targets: aarch64-unknown-linux-gnu + + # - name: Install system dependencies + # run: | + # sudo apt-get update + # sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev \ + # libappindicator3-dev librsvg2-dev patchelf gcc-aarch64-linux-gnu \ + # g++-aarch64-linux-gnu + + # - name: Install pnpm + # run: npm i -g pnpm + + # - name: Install frontend dependencies + # run: pnpm install + + # - uses: benjlevesque/short-sha@v2.1 + # id: short-sha + # with: + # length: 7 + + # - name: Install cross + # run: | + # cargo install cross + + # - uses: tauri-apps/tauri-action@v0 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # PKG_CONFIG_ALLOW_CROSS: 1 + # with: + # tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} + # releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" + # releaseBody: | + # "${{ github.event.head_commit.message }}" + # See the assets to download this version and install. + # releaseDraft: false + # prerelease: true + # tauriScript: pnpm tauri + # args: --target aarch64-unknown-linux-gnu --runner cross diff --git a/.github/workflows/tauri-mac.yml b/.github/workflows/tauri-mac.yml index cf843fc..304f26d 100644 --- a/.github/workflows/tauri-mac.yml +++ b/.github/workflows/tauri-mac.yml @@ -1,42 +1,42 @@ -name: Publish (MacOS) -on: [push] - -jobs: - publish-tauri-amd64: - permissions: - contents: write - runs-on: macos-latest - steps: - - uses: actions/checkout@v3 - - - name: setup node - uses: actions/setup-node@v3 - with: - node-version: 16 - - - name: install Rust nightly - uses: dtolnay/rust-toolchain@nightly - - - name: Install pnpm - run: npm i -g pnpm - - - name: Install frontend dependencies - run: pnpm install - - - uses: benjlevesque/short-sha@v2.1 - id: short-sha - with: - length: 7 - - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} - releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" - releaseBody: | - "${{ github.event.head_commit.message }}" - See the assets to download this version and install. - releaseDraft: false - prerelease: true - tauriScript: pnpm tauri +name: Publish (MacOS) +on: [push] + +jobs: + publish-tauri-amd64: + permissions: + contents: write + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: install Rust nightly + uses: dtolnay/rust-toolchain@nightly + + - name: Install pnpm + run: npm i -g pnpm + + - name: Install frontend dependencies + run: pnpm install + + - uses: benjlevesque/short-sha@v2.1 + id: short-sha + with: + length: 7 + + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} + releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" + releaseBody: | + "${{ github.event.head_commit.message }}" + See the assets to download this version and install. + releaseDraft: false + prerelease: true + tauriScript: pnpm tauri diff --git a/.github/workflows/tauri-win.yml b/.github/workflows/tauri-win.yml index f3d796a..e9822d4 100644 --- a/.github/workflows/tauri-win.yml +++ b/.github/workflows/tauri-win.yml @@ -1,42 +1,42 @@ -name: Publish (Windows) -on: [push] - -jobs: - publish-tauri-amd64: - permissions: - contents: write - runs-on: windows-latest - steps: - - uses: actions/checkout@v3 - - - name: setup node - uses: actions/setup-node@v3 - with: - node-version: 16 - - - name: install Rust nightly - uses: dtolnay/rust-toolchain@nightly - - - name: Install pnpm - run: npm i -g pnpm - - - name: Install frontend dependencies - run: pnpm install - - - uses: benjlevesque/short-sha@v2.1 - id: short-sha - with: - length: 7 - - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} - releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" - releaseBody: | - "${{ github.event.head_commit.message }}" - See the assets to download this version and install. - releaseDraft: false - prerelease: true - tauriScript: pnpm tauri +name: Publish (Windows) +on: [push] + +jobs: + publish-tauri-amd64: + permissions: + contents: write + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: install Rust nightly + uses: dtolnay/rust-toolchain@nightly + + - name: Install pnpm + run: npm i -g pnpm + + - name: Install frontend dependencies + run: pnpm install + + - uses: benjlevesque/short-sha@v2.1 + id: short-sha + with: + length: 7 + + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tagName: wormhole-dev-${{ steps.short-sha.outputs.sha }} + releaseName: "Wormhole (Dev) ${{ steps.short-sha.outputs.sha }}" + releaseBody: | + "${{ github.event.head_commit.message }}" + See the assets to download this version and install. + releaseDraft: false + prerelease: true + tauriScript: pnpm tauri diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..1f2dbf7 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,3 @@ +tasks: + - init: pnpm install && pnpm run build && cargo build + command: pnpm run dev && cargo watch -x run diff --git a/.prettierrc b/.prettierrc index dd0c950..7a5960d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,15 +1,15 @@ -{ - "arrowParens": "always", - "bracketSameLine": true, - "bracketSpacing": true, - "endOfLine": "lf", - "jsxSingleQuote": false, - "semi": true, - "singleQuote": false, - "tabWidth": 4, - "trailingComma": "es5", - "printWidth": 100, - "plugins": ["prettier-plugin-svelte"], - "pluginSearchDirs": ["."], - "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] -} +{ + "arrowParens": "always", + "bracketSameLine": true, + "bracketSpacing": true, + "endOfLine": "lf", + "jsxSingleQuote": false, + "semi": true, + "singleQuote": false, + "tabWidth": 4, + "trailingComma": "es5", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte"], + "pluginSearchDirs": ["."], + "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] +} diff --git a/.stylelintrc.json b/.stylelintrc.json index bde7a67..d098b77 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,18 +1,18 @@ -{ - "extends": "stylelint-config-standard-scss", - - "plugins": ["stylelint-scss"], - - "rules": { - "font-family-name-quotes": null, - "declaration-empty-line-before": null, - "font-family-no-missing-generic-family-keyword": null, - "no-empty-source": null, - "color-hex-length": null, - "shorthand-property-no-redundant-values": null, - "color-function-notation": null, - "alpha-value-notation": null, - "scss/at-import-partial-extension": null, - "at-rule-empty-line-before": null - } -} +{ + "extends": "stylelint-config-standard-scss", + + "plugins": ["stylelint-scss"], + + "rules": { + "font-family-name-quotes": null, + "declaration-empty-line-before": null, + "font-family-no-missing-generic-family-keyword": null, + "no-empty-source": null, + "color-hex-length": null, + "shorthand-property-no-redundant-values": null, + "color-function-notation": null, + "alpha-value-notation": null, + "scss/at-import-partial-extension": null, + "at-rule-empty-line-before": null + } +} diff --git a/README.md b/README.md index 84d2374..91db056 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,67 @@ # Wormhole -![Lines of code](https://img.shields.io/tokei/lines/github/RedstoneWizard08/Wormhole?label=lines%20of%20code&style=flat-square) +![Lines of code](https://tokei.rs/b1/github/RedstoneWizard08/Wormhole?category=code&label=lines+of+code&style=flat-square) ![GitHub all releases](https://img.shields.io/github/downloads/RedstoneWizard08/Wormhole/total?style=flat-square) [![crates.io (common)](https://img.shields.io/crates/v/wormhole-common?label=crates.io%20%28common%29&style=flat-square)](https://crates.io/crates/wormhole-common) [![crates.io (cli)](https://img.shields.io/crates/v/wormhole-cli?label=crates.io%20%28cli%29&style=flat-square)](https://crates.io/crates/wormhole-cli) -A new launcher and mod manager for Kerbal Space Program and Kerbal Space Program 2. - -The (unofficial) successor to CKAN. +A centralized multi-game mod and modpack manager and launcher, supporting Steam, +Epic Games, and the Private Division launcher. [API Documentation](https://docs.rs/wormhole-common) ## Features - A fully featured mod manager and installer. -- Supports both KSP 1 and KSP 2. +- Supports many different games. +- Full CurseForge integration. +- Full Modrinth integration. - Full SpaceDock integration. - Full CKAN integration (See: https://github.com/RedstoneWizard08/CKANDex) - Available for many platforms. - Easy-to-use UI. -- Super fast! -- Memory-efficient! +- Blazingly fast. +- Super memory-efficient. ## Roadmap - [x] Support for KSP 2 - [x] Support for KSP 1 +- [ ] Support for Minecraft +- [ ] Support for other suggested games. - [x] Support for Windows, Linux, and MacOS -- [x] Support for any steam library location +- [x] Support for any Steam library location +- [ ] Support for any Epic Games library location - [x] Support for Private Division launcher - [x] Mod installation & browsing from SpaceDock +- [ ] Mod installation & browsing from CKAN +- [ ] Mod installation & browsing from CurseForge +- [ ] Mod installation & browsing from Modrinth +- [ ] Modpack installation & browsing from SpaceDock +- [ ] Modpack installation & browsing from CKAN +- [ ] Modpack installation & browsing from CurseForge +- [ ] Modpack installation & browsing from Modrinth - [x] GUI app - [x] Full instances support - [x] Friendly UI - [x] Fast UI - [x] 100% Open Source -- [x] Automated SpaceWarp installation -- [x] SvelteKit rewrite -- [x] CLI app (WIP) - -## Long-term plans - -- [ ] Better settings -- [ ] Installed mod discovery -- [ ] Full modpack support -- [ ] Mod configuration editor -- [ ] Mod dependency resolution -- [ ] Mod conflict resolution -- [ ] Game version compatibility checking -- [ ] Mod installation & browsing from CKAN -- [ ] Mod installation & browsing from CurseForge +- [ ] CLI app +- [ ] Memory & CPU settings +- [ ] General settings +- [ ] Network limiting settings +- [ ] Mod config editor +- [ ] Mod dependency resolution & installation +- [ ] Mod conflict resolution (KSP 1 & KSP 2) +- [ ] Game version compatibility filter +- [ ] Game log viewer +- [ ] Modpack export & management +- [ ] Modpack creator & editor (CLI) + +## History + +Wormhole was originally known as the SpaceWarp Installer, and then @Rexicon226 and +@RedstoneWizard08 decided to expand it out into a fully fledged game launcher and +mod manager for KSP 1 and KSP 2. After about 6 months, @RedstoneWizard08 then decided +to expand it out into a general mod manager and game launcher to support many other +games (which can be suggested via issues). diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 390ea14..eae3bc4 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -1,75 +1,75 @@ -use clap::{Parser, Subcommand}; -use wormhole_common::instances::KSPGame; - -#[derive(Parser, Debug, Clone)] -#[command(author, version, about, long_about = None)] -pub struct Cli { - #[arg(short, long)] - pub verbose: bool, - - #[command(subcommand)] - pub command: Option, -} - -#[derive(Subcommand, Debug, Clone)] -pub enum Commands { - #[command(name = "spacedock")] - SpaceDock { - #[command(subcommand)] - command: Option, - }, - - CKAN { - #[command(subcommand)] - command: Option, - }, - - #[command(name = "curseforge")] - CurseForge { - #[command(subcommand)] - command: Option, - }, - - Instance { - #[command(subcommand)] - command: Option, - }, -} - -#[derive(Subcommand, Debug, Clone)] -pub enum ModCommands { - Info { - #[arg(value_enum)] - game_id: KSPGame, - id: String, - }, - - Install { - #[arg(value_enum)] - game_id: KSPGame, - id: String, - instance_id: i32, - }, - - Remove { - #[arg(value_enum)] - game_id: KSPGame, - id: String, - instance_id: i32, - }, - - Browse { - #[arg(value_enum)] - game_id: KSPGame, - - name_filter: Option, - }, -} - -#[derive(Subcommand, Debug, Clone)] -pub enum InstanceCommands { - List {}, - Create {}, - Delete {}, - Info {}, -} +use clap::{Parser, Subcommand}; +use wormhole_common::instances::KSPGame; + +#[derive(Parser, Debug, Clone)] +#[command(author, version, about, long_about = None)] +pub struct Cli { + #[arg(short, long)] + pub verbose: bool, + + #[command(subcommand)] + pub command: Option, +} + +#[derive(Subcommand, Debug, Clone)] +pub enum Commands { + #[command(name = "spacedock")] + SpaceDock { + #[command(subcommand)] + command: Option, + }, + + CKAN { + #[command(subcommand)] + command: Option, + }, + + #[command(name = "curseforge")] + CurseForge { + #[command(subcommand)] + command: Option, + }, + + Instance { + #[command(subcommand)] + command: Option, + }, +} + +#[derive(Subcommand, Debug, Clone)] +pub enum ModCommands { + Info { + #[arg(value_enum)] + game_id: KSPGame, + id: String, + }, + + Install { + #[arg(value_enum)] + game_id: KSPGame, + id: String, + instance_id: i32, + }, + + Remove { + #[arg(value_enum)] + game_id: KSPGame, + id: String, + instance_id: i32, + }, + + Browse { + #[arg(value_enum)] + game_id: KSPGame, + + name_filter: Option, + }, +} + +#[derive(Subcommand, Debug, Clone)] +pub enum InstanceCommands { + List {}, + Create {}, + Delete {}, + Info {}, +} diff --git a/cli/src/commands/ckan/mod.rs b/cli/src/commands/ckan/mod.rs index 0f7c7e0..f6feba2 100644 --- a/cli/src/commands/ckan/mod.rs +++ b/cli/src/commands/ckan/mod.rs @@ -1,93 +1,101 @@ -use crate::cli::ModCommands; -use ckandex::{Mod, ModType, QueryBuilder, IdFilter}; -use wormhole_common::ckan::{query::get_mods, setup_ckan}; - -pub mod install; - -use wormhole_common::ckan::{KSP1_CACHE_CLIENT, KSP2_CACHE_CLIENT}; -use wormhole_common::instances::KSPGame; - -pub async fn match_command(command: ModCommands) -> bool { - println!("+ Setting up NetKAN repositories..."); - - setup_ckan().await; - - match command { - ModCommands::Browse { - game_id, - name_filter, - } => { - println!("+ Querying mods..."); - - let mods = get_mods(game_id).await; - - println!("+ Filtering mods..."); - - let all_mods = [mods.netkans, mods.frozen].concat(); - - let mods: Vec = all_mods - .iter() - .filter(|item| { - let mut ok = !item.name.eq(""); - - if ok { - if let Some(name_filter) = name_filter.clone() { - ok = item - .name - .to_lowercase() - .contains(&name_filter.to_lowercase()); - } - } - - return ok; - }) - .cloned() - .collect(); - - println!("+ Found {} mods!", mods.len()); - - for item in mods { - let kind = match item.kind { - ModType::NETKAN => "Live", - ModType::FROZEN => "Frozen", - }; - - println!( - "=> {} ({}) [{}] | {}", - item.name, - item.id, - kind, - item.description.unwrap_or(" ".to_string()) - ); - } - - return true; - } - - ModCommands::Info { id, game_id } => { - let mut query = QueryBuilder::new(); - let query = query.add(IdFilter::new(id)).build(); - - let mut client = KSP1_CACHE_CLIENT.lock().unwrap(); - - if game_id == KSPGame::KSP2 { - client = KSP2_CACHE_CLIENT.lock().unwrap(); - } - - let client = client.clone().unwrap(); - let resp = query.execute(client); - - println!("{:?}", resp); - - return true; - } - - ModCommands::Install { id, instance_id, game_id } => { - return false; - } - - ModCommands::Remove { id, instance_id, game_id } => { - return false; - } - }; -} +use crate::cli::ModCommands; +use ckandex::{IdFilter, Mod, ModType, QueryBuilder}; +use wormhole_common::ckan::{query::get_mods, setup_ckan}; + +pub mod install; + +use wormhole_common::ckan::{KSP1_CACHE_CLIENT, KSP2_CACHE_CLIENT}; +use wormhole_common::instances::KSPGame; + +pub async fn match_command(command: ModCommands) -> bool { + println!("+ Setting up NetKAN repositories..."); + + setup_ckan().await; + + match command { + ModCommands::Browse { + game_id, + name_filter, + } => { + println!("+ Querying mods..."); + + let mods = get_mods(game_id).await; + + println!("+ Filtering mods..."); + + let all_mods = [mods.netkans, mods.frozen].concat(); + + let mods: Vec = all_mods + .iter() + .filter(|item| { + let mut ok = !item.name.eq(""); + + if ok { + if let Some(name_filter) = name_filter.clone() { + ok = item + .name + .to_lowercase() + .contains(&name_filter.to_lowercase()); + } + } + + return ok; + }) + .cloned() + .collect(); + + println!("+ Found {} mods!", mods.len()); + + for item in mods { + let kind = match item.kind { + ModType::NETKAN => "Live", + ModType::FROZEN => "Frozen", + }; + + println!( + "=> {} ({}) [{}] | {}", + item.name, + item.id, + kind, + item.description.unwrap_or(" ".to_string()) + ); + } + + return true; + } + + ModCommands::Info { id, game_id } => { + let mut query = QueryBuilder::new(); + let query = query.add(IdFilter::new(id)).build(); + + let mut client = KSP1_CACHE_CLIENT.lock().unwrap(); + + if game_id == KSPGame::KSP2 { + client = KSP2_CACHE_CLIENT.lock().unwrap(); + } + + let client = client.clone().unwrap(); + let resp = query.execute(client); + + println!("{:?}", resp); + + return true; + } + + ModCommands::Install { + id, + instance_id, + game_id, + } => { + return false; + } + + ModCommands::Remove { + id, + instance_id, + game_id, + } => { + return false; + } + }; +} diff --git a/cli/src/main.rs b/cli/src/main.rs index 3db7c1e..feaad91 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,63 +1,63 @@ -#![allow(clippy::needless_return)] - -use std::env; - -use clap::{Parser, CommandFactory}; -use commands::{ckan, curseforge, instance, spacedock}; -use tokio::main; - -use cli::{Cli, Commands}; - -pub mod auth; -pub mod cli; -pub mod commands; - -#[main] -pub async fn main() { - if env::var("GITHUB_TOKEN").is_err() { - env::set_var("GITHUB_TOKEN", ""); - } - - let cli = Cli::parse(); - let verbose = cli.verbose; - - if verbose { - println!("Command: {:?}", cli.command); - } - - let mut ok: bool = false; - - if let Some(command) = cli.command { - match command { - Commands::SpaceDock { command } => { - if let Some(command) = command { - ok = spacedock::match_command(command).await; - } - } - - Commands::CKAN { command } => { - if let Some(command) = command { - ok = ckan::match_command(command).await; - } - } - - Commands::CurseForge { command } => { - if let Some(command) = command { - ok = curseforge::match_command(command).await; - } - } - - Commands::Instance { command } => { - if let Some(command) = command { - ok = instance::match_command(command).await; - } - } - }; - } - - if !ok { - let mut cmd = Cli::command(); - - cmd.print_help().unwrap(); - } -} +#![allow(clippy::needless_return)] + +use std::env; + +use clap::{CommandFactory, Parser}; +use commands::{ckan, curseforge, instance, spacedock}; +use tokio::main; + +use cli::{Cli, Commands}; + +pub mod auth; +pub mod cli; +pub mod commands; + +#[main] +pub async fn main() { + if env::var("GITHUB_TOKEN").is_err() { + env::set_var("GITHUB_TOKEN", ""); + } + + let cli = Cli::parse(); + let verbose = cli.verbose; + + if verbose { + println!("Command: {:?}", cli.command); + } + + let mut ok: bool = false; + + if let Some(command) = cli.command { + match command { + Commands::SpaceDock { command } => { + if let Some(command) = command { + ok = spacedock::match_command(command).await; + } + } + + Commands::CKAN { command } => { + if let Some(command) = command { + ok = ckan::match_command(command).await; + } + } + + Commands::CurseForge { command } => { + if let Some(command) = command { + ok = curseforge::match_command(command).await; + } + } + + Commands::Instance { command } => { + if let Some(command) = command { + ok = instance::match_command(command).await; + } + } + }; + } + + if !ok { + let mut cmd = Cli::command(); + + cmd.print_help().unwrap(); + } +} diff --git a/gui/tauri.conf.json b/gui/tauri.conf.json index fa8ddf2..f303ce5 100644 --- a/gui/tauri.conf.json +++ b/gui/tauri.conf.json @@ -1,75 +1,75 @@ -{ - "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/tooling/cli/schema.json", - "build": { - "beforeDevCommand": "pnpm app:dev", - "beforeBuildCommand": "pnpm app:build", - "devPath": "http://localhost:1420", - "distDir": "../build", - "withGlobalTauri": true - }, - "package": { - "productName": "Wormhole", - "version": "1.0.0" - }, - "tauri": { - "allowlist": { - "all": true, - "shell": { - "all": false, - "open": true - } - }, - "bundle": { - "active": true, - "category": "DeveloperTool", - "copyright": "", - "deb": { - "depends": [] - }, - "externalBin": [], - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "identifier": "io.github.redstonewizard08.wormhole", - "longDescription": "", - "macOS": { - "entitlements": null, - "exceptionDomain": "", - "frameworks": [], - "providerShortName": null, - "signingIdentity": null - }, - "resources": [], - "shortDescription": "The (unofficial) successor to CKAN.", - "targets": "all", - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, - "security": { - "csp": null - }, - "updater": { - "active": false - }, - "windows": [ - { - "fullscreen": false, - "height": 800, - "width": 1200, - "resizable": true, - "title": "Wormhole", - "minHeight": 400, - "minWidth": 600, - "maximized": true, - "theme": "Dark" - } - ] - } -} +{ + "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/tooling/cli/schema.json", + "build": { + "beforeDevCommand": "pnpm app:dev", + "beforeBuildCommand": "pnpm app:build", + "devPath": "http://localhost:1420", + "distDir": "../build", + "withGlobalTauri": true + }, + "package": { + "productName": "Wormhole", + "version": "1.0.0" + }, + "tauri": { + "allowlist": { + "all": true, + "shell": { + "all": false, + "open": true + } + }, + "bundle": { + "active": true, + "category": "DeveloperTool", + "copyright": "", + "deb": { + "depends": [] + }, + "externalBin": [], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "identifier": "io.github.redstonewizard08.wormhole", + "longDescription": "", + "macOS": { + "entitlements": null, + "exceptionDomain": "", + "frameworks": [], + "providerShortName": null, + "signingIdentity": null + }, + "resources": [], + "shortDescription": "The (unofficial) successor to CKAN.", + "targets": "all", + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + } + }, + "security": { + "csp": null + }, + "updater": { + "active": false + }, + "windows": [ + { + "fullscreen": false, + "height": 800, + "width": 1200, + "resizable": true, + "title": "Wormhole", + "minHeight": 400, + "minWidth": 600, + "maximized": true, + "theme": "Dark" + } + ] + } +} diff --git a/package.json b/package.json index 81b1dea..62e1c6d 100644 --- a/package.json +++ b/package.json @@ -1,94 +1,94 @@ -{ - "name": "wormhole", - "version": "1.0.0", - "description": "", - "main": "index.js", - "author": "SpaceWarpDev", - "license": "MIT", - "type": "module", - "keywords": [ - "kerbalspaceprogram", - "kerbalspaceprogram2", - "ksp", - "ksp2", - "spacewarp", - "spacewarpdev", - "installer", - "tauri", - "wormhole", - "vite", - "preact", - "modloader", - "rust", - "typescript", - "sass" - ], - "scripts": { - "app:dev": "vite", - "app:build": "tsc && vite build", - "app:preview": "vite preview", - "dev": "tauri dev", - "build": "tauri build", - "tauri": "tauri", - "fmt": "prettier --write . && cargo fmt", - "web:dev": "TAURI_WEB_DEV=1 vite", - "web:build": "TAURI_WEB_DEV=1 vite build", - "lint:eslint": "eslint --ext .ts,.tsx,.svelte .", - "lint:stylelint": "stylelint **/*.scss **/*.css", - "lint:clippy": "cargo clippy", - "lint": "pnpm lint:eslint && pnpm lint:stylelint && pnpm lint:clippy", - "console": "ts-node app/scripts/console.ts", - "check": "svelte-kit sync && svelte-check", - "check:watch": "svelte-kit sync && svelte-check --watch", - "postinstall": "svelte-kit sync", - "serve": "serve -p 4000 build" - }, - "repository": { - "type": "git", - "url": "https://github.com/SpaceWarpDev/Space-Warp-Installer" - }, - "devDependencies": { - "@babel/core": "^7.21.3", - "@sveltejs/adapter-static": "^2.0.1", - "@sveltejs/kit": "^1.14.0", - "@tauri-apps/cli": "^1.2.3", - "@types/cookie": "^0.5.1", - "@types/dompurify": "^3.0.0", - "@types/marked": "^4.0.8", - "@types/node": "^18.15.3", - "@types/path-browserify": "^1.0.0", - "@types/source-map-support": "^0.5.6", - "@typescript-eslint/eslint-plugin": "^5.55.0", - "@typescript-eslint/parser": "^5.55.0", - "colorette": "^2.0.19", - "eslint": "^8.36.0", - "eslint-config-preact": "^1.3.0", - "eslint-plugin-svelte3": "^4.0.0", - "jest": "^29.5.0", - "postcss": "^8.4.21", - "prettier": "^2.8.4", - "prettier-plugin-svelte": "^2.10.0", - "puppeteer": "^19.7.5", - "sass": "^1.59.3", - "serve": "^14.2.0", - "stylelint": "^15.3.0", - "stylelint-config-standard-scss": "^7.0.1", - "stylelint-scss": "^4.5.0", - "svelte": "^3.57.0", - "svelte-check": "^3.1.4", - "ts-node": "^10.9.1", - "typescript": "^4.9.5", - "vite": "^4.2.0" - }, - "dependencies": { - "@fontsource/ubuntu": "^4.5.11", - "@fontsource/ubuntu-mono": "^4.5.11", - "@fortawesome/fontawesome-free": "^6.3.0", - "@tauri-apps/api": "^1.2.0", - "@types/wicg-file-system-access": "^2020.9.5", - "axios": "^1.3.4", - "dompurify": "^3.0.1", - "eruda": "^2.11.3", - "marked": "^4.2.12" - } -} +{ + "name": "wormhole", + "version": "1.0.0", + "description": "", + "main": "index.js", + "author": "SpaceWarpDev", + "license": "MIT", + "type": "module", + "keywords": [ + "kerbalspaceprogram", + "kerbalspaceprogram2", + "ksp", + "ksp2", + "spacewarp", + "spacewarpdev", + "installer", + "tauri", + "wormhole", + "vite", + "preact", + "modloader", + "rust", + "typescript", + "sass" + ], + "scripts": { + "app:dev": "vite", + "app:build": "tsc && vite build", + "app:preview": "vite preview", + "dev": "tauri dev", + "build": "tauri build", + "tauri": "tauri", + "fmt": "prettier --write . && cargo fmt", + "web:dev": "TAURI_WEB_DEV=1 vite", + "web:build": "TAURI_WEB_DEV=1 vite build", + "lint:eslint": "eslint --ext .ts,.tsx,.svelte .", + "lint:stylelint": "stylelint **/*.scss **/*.css", + "lint:clippy": "cargo clippy", + "lint": "pnpm lint:eslint && pnpm lint:stylelint && pnpm lint:clippy", + "console": "ts-node app/scripts/console.ts", + "check": "svelte-kit sync && svelte-check", + "check:watch": "svelte-kit sync && svelte-check --watch", + "postinstall": "svelte-kit sync", + "serve": "serve -p 4000 build" + }, + "repository": { + "type": "git", + "url": "https://github.com/SpaceWarpDev/Space-Warp-Installer" + }, + "devDependencies": { + "@babel/core": "^7.21.3", + "@sveltejs/adapter-static": "^2.0.1", + "@sveltejs/kit": "^1.14.0", + "@tauri-apps/cli": "^1.2.3", + "@types/cookie": "^0.5.1", + "@types/dompurify": "^3.0.0", + "@types/marked": "^4.0.8", + "@types/node": "^18.15.3", + "@types/path-browserify": "^1.0.0", + "@types/source-map-support": "^0.5.6", + "@typescript-eslint/eslint-plugin": "^5.55.0", + "@typescript-eslint/parser": "^5.55.0", + "colorette": "^2.0.19", + "eslint": "^8.36.0", + "eslint-config-preact": "^1.3.0", + "eslint-plugin-svelte3": "^4.0.0", + "jest": "^29.5.0", + "postcss": "^8.4.21", + "prettier": "^2.8.4", + "prettier-plugin-svelte": "^2.10.0", + "puppeteer": "^19.7.5", + "sass": "^1.59.3", + "serve": "^14.2.0", + "stylelint": "^15.3.0", + "stylelint-config-standard-scss": "^7.0.1", + "stylelint-scss": "^4.5.0", + "svelte": "^3.57.0", + "svelte-check": "^3.1.4", + "ts-node": "^10.9.1", + "typescript": "^4.9.5", + "vite": "^4.2.0" + }, + "dependencies": { + "@fontsource/ubuntu": "^4.5.11", + "@fontsource/ubuntu-mono": "^4.5.11", + "@fortawesome/fontawesome-free": "^6.3.0", + "@tauri-apps/api": "^1.2.0", + "@types/wicg-file-system-access": "^2020.9.5", + "axios": "^1.3.4", + "dompurify": "^3.0.1", + "eruda": "^2.11.3", + "marked": "^4.2.12" + } +} diff --git a/scripts/console.ts b/scripts/console.ts index c2ab438..ec871ed 100644 --- a/scripts/console.ts +++ b/scripts/console.ts @@ -1,45 +1,45 @@ -import { blue, cyan, green, magenta, red, yellow } from "colorette"; -import puppeteer from "puppeteer"; - -const main = async () => { - const browser = await puppeteer.launch(); - const page = await browser.newPage(); - - page.on("console", (message) => { - const type = message.type().substr(0, 3).toUpperCase(); - - // eslint-disable-next-line no-unused-vars - const colors: { [key: string]: (text: string) => string } = { - LOG: (text) => text, - ERR: red, - WAR: yellow, - INF: cyan, - }; - - const color = colors[type] || blue; - - console.log(color(`${type} ${message.text()}`)); - }); - - page.on("pageerror", ({ message }) => console.log(red(message))); - - page.on( - "response", - (response) => - !response.status().toString().startsWith("2") && - !response.status().toString().startsWith("3") && - console.log(green(`${response.status()} ${response.url()}`)) - ); - - page.on("requestfailed", (request) => - console.log(magenta(`${request.failure()?.errorText} ${request.url()}`)) - ); - - await page.goto(process.argv[2]); - - await new Promise((r) => setTimeout(r, 999999999)); - - await browser.close(); -}; - -main(); +import { blue, cyan, green, magenta, red, yellow } from "colorette"; +import puppeteer from "puppeteer"; + +const main = async () => { + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + + page.on("console", (message) => { + const type = message.type().substr(0, 3).toUpperCase(); + + // eslint-disable-next-line no-unused-vars + const colors: { [key: string]: (text: string) => string } = { + LOG: (text) => text, + ERR: red, + WAR: yellow, + INF: cyan, + }; + + const color = colors[type] || blue; + + console.log(color(`${type} ${message.text()}`)); + }); + + page.on("pageerror", ({ message }) => console.log(red(message))); + + page.on( + "response", + (response) => + !response.status().toString().startsWith("2") && + !response.status().toString().startsWith("3") && + console.log(green(`${response.status()} ${response.url()}`)) + ); + + page.on("requestfailed", (request) => + console.log(magenta(`${request.failure()?.errorText} ${request.url()}`)) + ); + + await page.goto(process.argv[2]); + + await new Promise((r) => setTimeout(r, 999999999)); + + await browser.close(); +}; + +main(); diff --git a/src/api/SpaceDock.ts b/src/api/SpaceDock.ts index 343a22a..35e7d32 100644 --- a/src/api/SpaceDock.ts +++ b/src/api/SpaceDock.ts @@ -1,47 +1,47 @@ -import axios from "axios"; - -import { finishBrowseResult } from "./models/browse"; -import { finishFullModInfo } from "./models/modinfo/full"; - -export class SpaceDockAPI { - private base: string; - - public constructor(baseUrl?: string) { - this.base = baseUrl || SpaceDockAPI.getDefaultAPIUrl(); - } - - public static getDefaultAPIUrl() { - return import.meta.env.DEV ? "/_spacedock/api" : "https://spacedock.info/api"; - } - - public async getMods(page = 1, count = 30) { - const response = await axios.get(`${this.base}/browse?page=${page}&count=${count}`); - - return finishBrowseResult(response.data); - } - - public async getMod(id: string | number) { - const response = await axios.get(`${this.base}/mod/${id}`); - - return finishFullModInfo(response.data); - } - - public async getModDownload(id: string | number) { - const response = await axios.get(`${this.base}/mod/${id}/latest`); - - return ( - (this.base == "/_spacedock/api" ? "/_spacedock" : this.base) + - response.data.download_path - ); - } - - public async getModsForGame(gameId: number, page = 1, count = 30) { - // This is not implemented yet! To look at the implementation, see this PR: - // KSP-SpaceDock/SpaceDock#466 - const response = await axios.get( - `${this.base}/browse?page=${page}&count=${count}&game_id=${gameId}` - ); - - return finishBrowseResult(response.data); - } -} +import axios from "axios"; + +import { finishBrowseResult } from "./models/browse"; +import { finishFullModInfo } from "./models/modinfo/full"; + +export class SpaceDockAPI { + private base: string; + + public constructor(baseUrl?: string) { + this.base = baseUrl || SpaceDockAPI.getDefaultAPIUrl(); + } + + public static getDefaultAPIUrl() { + return import.meta.env.DEV ? "/_spacedock/api" : "https://spacedock.info/api"; + } + + public async getMods(page = 1, count = 30) { + const response = await axios.get(`${this.base}/browse?page=${page}&count=${count}`); + + return finishBrowseResult(response.data); + } + + public async getMod(id: string | number) { + const response = await axios.get(`${this.base}/mod/${id}`); + + return finishFullModInfo(response.data); + } + + public async getModDownload(id: string | number) { + const response = await axios.get(`${this.base}/mod/${id}/latest`); + + return ( + (this.base == "/_spacedock/api" ? "/_spacedock" : this.base) + + response.data.download_path + ); + } + + public async getModsForGame(gameId: number, page = 1, count = 30) { + // This is not implemented yet! To look at the implementation, see this PR: + // KSP-SpaceDock/SpaceDock#466 + const response = await axios.get( + `${this.base}/browse?page=${page}&count=${count}&game_id=${gameId}` + ); + + return finishBrowseResult(response.data); + } +} diff --git a/src/api/boot.ts b/src/api/boot.ts index ea43e3b..9fe4c52 100644 --- a/src/api/boot.ts +++ b/src/api/boot.ts @@ -1,13 +1,13 @@ -import { invoke_proxy } from "./invoke"; - -export const backend_boot = async () => { - console.log("Backend booting..."); - - await invoke_proxy("backend_boot", undefined); - - console.log("Backend booted."); - - const mods = await invoke_proxy("read_mod_json", undefined); - - console.log("Mods:", mods); -}; +import { invoke_proxy } from "./invoke"; + +export const backend_boot = async () => { + console.log("Backend booting..."); + + await invoke_proxy("backend_boot", undefined); + + console.log("Backend booted."); + + const mods = await invoke_proxy("read_mod_json", undefined); + + console.log("Mods:", mods); +}; diff --git a/src/api/browse.ts b/src/api/browse.ts index 2349b1c..ba631ca 100644 --- a/src/api/browse.ts +++ b/src/api/browse.ts @@ -1,13 +1,13 @@ -import type { DropdownItem } from "./dropdown"; - -export const gameItems: DropdownItem[] = [ - { - id: 3102, - text: "KSP 1", - }, - - { - id: 22407, - text: "KSP 2", - }, -]; +import type { DropdownItem } from "./dropdown"; + +export const gameItems: DropdownItem[] = [ + { + id: 3102, + text: "KSP 1", + }, + + { + id: 22407, + text: "KSP 2", + }, +]; diff --git a/src/api/dev.ts b/src/api/dev.ts index a2f0852..d0e4de4 100644 --- a/src/api/dev.ts +++ b/src/api/dev.ts @@ -1,96 +1,96 @@ -import { mockIPC } from "@tauri-apps/api/mocks"; -import { type InstanceInfo, KSPGame } from "./instance"; -import { SpaceDockAPI } from "./SpaceDock"; -import type { InvokeFunction, ModsIntegrity } from "./invoke"; -import { download } from "./mocks/download"; - -export const repeat = (arr: T[], n: number): T[] => { - const final: T[] = []; - - for (let i = 0; i < n; i++) { - final.push(...arr); - } - - return final; -}; - -export const DEV_Instances: InstanceInfo[] = repeat( - [ - { - id: 0, - name: "KSP2 Default Instance", - game: KSPGame.KSP2, - install_path: "/home/steam/.steam/root/steamapps/common/Kerbal Space Program 2", - mods: [], - }, - { - id: 1, - name: "KSP1 Default Instance", - game: KSPGame.KSP1, - install_path: "/home/steam/.steam/root/steamapps/common/Kerbal Space Program", - mods: [], - }, - ], - 1 -); - -export const createMockAPI = () => { - mockIPC((async ( - cmd: K, - args: InvokeFunction[K][0] - ): Promise => { - switch (cmd) { - case "install_spacewarp": - await download(); - return "Success"; - - case "uninstall_spacewarp": - return "Success"; - - case "get_install_dir": - return "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Kerbal Space Program 2"; - - case "launch": - return undefined; - - case "get_instances": - return DEV_Instances.filter((v) => v.game == (args as any | undefined)?.gameId); - - case "get_instance_info": - const id = (args as InvokeFunction["get_instance_info"][0]).instanceId; - - return DEV_Instances.find((v) => v.id == id); - - case "get_mods": - const fargs = args as InvokeFunction["get_mods"][0]; - - return await new SpaceDockAPI().getModsForGame( - fargs.gameId, - fargs.page, - fargs.count - ); - - case "get_mod": - return await new SpaceDockAPI().getMod( - (args as InvokeFunction["get_mod"][0]).modId - ); - - case "get_mod_download": - return await new SpaceDockAPI().getModDownload( - (args as InvokeFunction["get_mod_download"][0]).modId - ); - - case "install_mod": - return await new SpaceDockAPI().getModDownload( - (args as InvokeFunction["install_mod"][0]).modId - ); - - case "read_mod_json": - const res: ModsIntegrity = { - mods: [], - }; - - return res; - } - }) as any); -}; +import { mockIPC } from "@tauri-apps/api/mocks"; +import { type InstanceInfo, KSPGame } from "./instance"; +import { SpaceDockAPI } from "./SpaceDock"; +import type { InvokeFunction, ModsIntegrity } from "./invoke"; +import { download } from "./mocks/download"; + +export const repeat = (arr: T[], n: number): T[] => { + const final: T[] = []; + + for (let i = 0; i < n; i++) { + final.push(...arr); + } + + return final; +}; + +export const DEV_Instances: InstanceInfo[] = repeat( + [ + { + id: 0, + name: "KSP2 Default Instance", + game: KSPGame.KSP2, + install_path: "/home/steam/.steam/root/steamapps/common/Kerbal Space Program 2", + mods: [], + }, + { + id: 1, + name: "KSP1 Default Instance", + game: KSPGame.KSP1, + install_path: "/home/steam/.steam/root/steamapps/common/Kerbal Space Program", + mods: [], + }, + ], + 1 +); + +export const createMockAPI = () => { + mockIPC((async ( + cmd: K, + args: InvokeFunction[K][0] + ): Promise => { + switch (cmd) { + case "install_spacewarp": + await download(); + return "Success"; + + case "uninstall_spacewarp": + return "Success"; + + case "get_install_dir": + return "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Kerbal Space Program 2"; + + case "launch": + return undefined; + + case "get_instances": + return DEV_Instances.filter((v) => v.game == (args as any | undefined)?.gameId); + + case "get_instance_info": + const id = (args as InvokeFunction["get_instance_info"][0]).instanceId; + + return DEV_Instances.find((v) => v.id == id); + + case "get_mods": + const fargs = args as InvokeFunction["get_mods"][0]; + + return await new SpaceDockAPI().getModsForGame( + fargs.gameId, + fargs.page, + fargs.count + ); + + case "get_mod": + return await new SpaceDockAPI().getMod( + (args as InvokeFunction["get_mod"][0]).modId + ); + + case "get_mod_download": + return await new SpaceDockAPI().getModDownload( + (args as InvokeFunction["get_mod_download"][0]).modId + ); + + case "install_mod": + return await new SpaceDockAPI().getModDownload( + (args as InvokeFunction["install_mod"][0]).modId + ); + + case "read_mod_json": + const res: ModsIntegrity = { + mods: [], + }; + + return res; + } + }) as any); +}; diff --git a/src/api/dropdown.ts b/src/api/dropdown.ts index 0b4fed9..24d7ad4 100644 --- a/src/api/dropdown.ts +++ b/src/api/dropdown.ts @@ -1,4 +1,4 @@ -export interface DropdownItem { - id: string | number; - text: string; -} +export interface DropdownItem { + id: string | number; + text: string; +} diff --git a/src/api/instance.ts b/src/api/instance.ts index ed850e7..3b114b4 100644 --- a/src/api/instance.ts +++ b/src/api/instance.ts @@ -1,38 +1,38 @@ -// The expected size of KSP1's `steam_api64.dll` in bytes. -// This helps to make sure that the game is not pirated. -// File path: `[KSP1_ROOT]/KSP_x64_Data/Plugins/x86_64/steam_api64.dll` -// Information from: SteamDB, DepotDownloader, KSP1 Installed Files -export const KSP1_STEAM_API_SIZE = 249120; - -// The expected size of KSP2's `steam_api64.dll` in bytes. -// This helps to make sure that the game is not pirated. -// File path: `[KSP2_ROOT]/KSP2_x64_Data/Plugins/x86_64/steam_api64.dll` -// Information from: SteamDB, DepotDownloader, KSP2 Installed Files -export const KSP2_STEAM_API_SIZE = 295336; - -export interface KSPGameType { - KSP1: number; - KSP2: number; -} - -// This uses the game's ID in SpaceDock as the enum value -export const KSPGame: KSPGameType = { - KSP1: 3102, - KSP2: 22407, -}; - -export interface InstanceMod { - id: number; - name: string; - paths: string[]; -} - -export interface InstanceInfo { - id: number; - name: string; - game: number; - mods: InstanceMod[]; - install_path: string; - description?: string; - time_played?: string; -} +// The expected size of KSP1's `steam_api64.dll` in bytes. +// This helps to make sure that the game is not pirated. +// File path: `[KSP1_ROOT]/KSP_x64_Data/Plugins/x86_64/steam_api64.dll` +// Information from: SteamDB, DepotDownloader, KSP1 Installed Files +export const KSP1_STEAM_API_SIZE = 249120; + +// The expected size of KSP2's `steam_api64.dll` in bytes. +// This helps to make sure that the game is not pirated. +// File path: `[KSP2_ROOT]/KSP2_x64_Data/Plugins/x86_64/steam_api64.dll` +// Information from: SteamDB, DepotDownloader, KSP2 Installed Files +export const KSP2_STEAM_API_SIZE = 295336; + +export interface KSPGameType { + KSP1: number; + KSP2: number; +} + +// This uses the game's ID in SpaceDock as the enum value +export const KSPGame: KSPGameType = { + KSP1: 3102, + KSP2: 22407, +}; + +export interface InstanceMod { + id: number; + name: string; + paths: string[]; +} + +export interface InstanceInfo { + id: number; + name: string; + game: number; + mods: InstanceMod[]; + install_path: string; + description?: string; + time_played?: string; +} diff --git a/src/api/invoke.ts b/src/api/invoke.ts index 1fd88ed..eb9c3d8 100644 --- a/src/api/invoke.ts +++ b/src/api/invoke.ts @@ -1,94 +1,94 @@ -import type { InstanceInfo } from "./instance"; -import type { BrowseResult } from "./models/browse"; -import type { FullModInfo } from "./models/modinfo/full"; - -export interface InstanceArgs { - instanceId: number; -} - -export interface ModArgs { - modId: number; - gameId: number; -} - -export interface ModsArgs { - gameId: number; - page: number; - count: number; -} - -export interface QueryData { - query: string; - modName: string; -} - -export interface GameArgs { - gameId: number; -} - -export interface InstanceUpdateArgs { - instanceId: number; - description: string; -} - -export interface ModIntegrity { - name: string; - date_installed: string; - size: number; - install_path: string; -} - -export interface ModsIntegrity { - mods: ModIntegrity[]; -} - -export interface AddInstanceArgs { - gameId: number; - name: string; - installPath: string; -} - -export interface GetInstances { - gameId: number; -} - -export interface InvokeFunction { - install_spacewarp: [undefined, string]; - uninstall_spacewarp: [undefined, string]; - - get_install_dir: [GameArgs, string]; - - launch: [InstanceArgs, undefined]; - - get_instances: [GetInstances, InstanceInfo[]]; - get_instance_info: [InstanceArgs, InstanceInfo]; - - get_mod: [ModArgs, FullModInfo]; - get_mod_download: [ModArgs, string]; - get_mods: [ModsArgs, BrowseResult]; - get_distance: [QueryData, undefined]; - - add_instance: [AddInstanceArgs, undefined]; - install_mod: [ModArgs & InstanceArgs, undefined]; - backend_boot: [undefined, undefined]; - read_mod_json: [undefined, ModsIntegrity]; - - update_description: [InstanceUpdateArgs, undefined]; - get_active_instance: [GameArgs, InstanceInfo | undefined]; - set_active_instance: [InstanceArgs, undefined]; - - delete_instance: [InstanceArgs, undefined]; -} - -export const invoke_proxy = async ( - action: K, - args: InvokeFunction[K][0] -): Promise => { - try { - const invoke = (await import("@tauri-apps/api")).invoke; - - return (await invoke(action, { ...args })) as any; - } catch (e) { - return e as any; - } -}; +import type { InstanceInfo } from "./instance"; +import type { BrowseResult } from "./models/browse"; +import type { FullModInfo } from "./models/modinfo/full"; + +export interface InstanceArgs { + instanceId: number; +} + +export interface ModArgs { + modId: number; + gameId: number; +} + +export interface ModsArgs { + gameId: number; + page: number; + count: number; +} + +export interface QueryData { + query: string; + modName: string; +} + +export interface GameArgs { + gameId: number; +} + +export interface InstanceUpdateArgs { + instanceId: number; + description: string; +} + +export interface ModIntegrity { + name: string; + date_installed: string; + size: number; + install_path: string; +} + +export interface ModsIntegrity { + mods: ModIntegrity[]; +} + +export interface AddInstanceArgs { + gameId: number; + name: string; + installPath: string; +} + +export interface GetInstances { + gameId: number; +} + +export interface InvokeFunction { + install_spacewarp: [undefined, string]; + uninstall_spacewarp: [undefined, string]; + + get_install_dir: [GameArgs, string]; + + launch: [InstanceArgs, undefined]; + + get_instances: [GetInstances, InstanceInfo[]]; + get_instance_info: [InstanceArgs, InstanceInfo]; + + get_mod: [ModArgs, FullModInfo]; + get_mod_download: [ModArgs, string]; + get_mods: [ModsArgs, BrowseResult]; + get_distance: [QueryData, undefined]; + + add_instance: [AddInstanceArgs, undefined]; + install_mod: [ModArgs & InstanceArgs, undefined]; + backend_boot: [undefined, undefined]; + read_mod_json: [undefined, ModsIntegrity]; + + update_description: [InstanceUpdateArgs, undefined]; + get_active_instance: [GameArgs, InstanceInfo | undefined]; + set_active_instance: [InstanceArgs, undefined]; + + delete_instance: [InstanceArgs, undefined]; +} + +export const invoke_proxy = async ( + action: K, + args: InvokeFunction[K][0] +): Promise => { + try { + const invoke = (await import("@tauri-apps/api")).invoke; + + return (await invoke(action, { ...args })) as any; + } catch (e) { + return e as any; + } +}; diff --git a/src/api/listen.ts b/src/api/listen.ts index e46fdcd..12be19b 100644 --- a/src/api/listen.ts +++ b/src/api/listen.ts @@ -1,31 +1,31 @@ -import type { UnlistenFn } from "@tauri-apps/api/event"; - -export interface DownloadProgress { - total: number; - received: number; -} - -export interface DownloadComplete { - size: number; -} - -export interface ListenEventType { - download_progress: DownloadProgress; - download_complete: DownloadComplete; -} - -export interface ListenEvent { - payload: T; -} - -// eslint-disable-next-line no-unused-vars -export type ListenHandler = (event: ListenEvent) => void; - -export const listen_proxy = async ( - action: K, - handler: ListenHandler -): Promise => { - const listen = (await import("@tauri-apps/api/event")).listen; - - return listen(action, handler); -}; +import type { UnlistenFn } from "@tauri-apps/api/event"; + +export interface DownloadProgress { + total: number; + received: number; +} + +export interface DownloadComplete { + size: number; +} + +export interface ListenEventType { + download_progress: DownloadProgress; + download_complete: DownloadComplete; +} + +export interface ListenEvent { + payload: T; +} + +// eslint-disable-next-line no-unused-vars +export type ListenHandler = (event: ListenEvent) => void; + +export const listen_proxy = async ( + action: K, + handler: ListenHandler +): Promise => { + const listen = (await import("@tauri-apps/api/event")).listen; + + return listen(action, handler); +}; diff --git a/src/api/mocks/download.ts b/src/api/mocks/download.ts index f1e0a95..7a31bcc 100644 --- a/src/api/mocks/download.ts +++ b/src/api/mocks/download.ts @@ -1,62 +1,62 @@ -import axios from "axios"; -import { emit } from "@tauri-apps/api/event"; - -export const toDataURI = (blob: Blob) => { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - - reader.onload = () => resolve(reader.result as string); - reader.onerror = () => reject(reader.error); - reader.onabort = () => reject(new Error("Read aborted!")); - - reader.readAsDataURL(blob); - }); -}; - -export const save = (url: string, name: string) => { - const a = document.createElement("a"); - - a.href = url; - a.download = name; - - document.body.appendChild(a); - - a.click(); - a.remove(); -}; - -export const download = async () => { - const url = "/_dev/BepInEx_x64_5.4.21.0.zip"; - const url2 = "/_dev/spacewarp-release-1.0.1.zip"; - - const resp = await axios.get(url, { - onDownloadProgress: (ev) => { - emit("download_progress", { - received: ev.loaded, - total: ev.total! * 2, - }); - }, - - responseType: "blob", - }); - - const resp2 = await axios.get(url2, { - onDownloadProgress: (ev) => { - emit("download_progress", { - received: ev.total! + ev.loaded, - total: ev.total! * 2, - }); - }, - - responseType: "blob", - }); - - const fileName = url.split("/").pop()!; - const fileName2 = url2.split("/").pop()!; - - const dataUri = await toDataURI(resp.data); - const dataUri2 = await toDataURI(resp2.data); - - save(dataUri, fileName); - save(dataUri2, fileName2); -}; +import axios from "axios"; +import { emit } from "@tauri-apps/api/event"; + +export const toDataURI = (blob: Blob) => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = () => resolve(reader.result as string); + reader.onerror = () => reject(reader.error); + reader.onabort = () => reject(new Error("Read aborted!")); + + reader.readAsDataURL(blob); + }); +}; + +export const save = (url: string, name: string) => { + const a = document.createElement("a"); + + a.href = url; + a.download = name; + + document.body.appendChild(a); + + a.click(); + a.remove(); +}; + +export const download = async () => { + const url = "/_dev/BepInEx_x64_5.4.21.0.zip"; + const url2 = "/_dev/spacewarp-release-1.0.1.zip"; + + const resp = await axios.get(url, { + onDownloadProgress: (ev) => { + emit("download_progress", { + received: ev.loaded, + total: ev.total! * 2, + }); + }, + + responseType: "blob", + }); + + const resp2 = await axios.get(url2, { + onDownloadProgress: (ev) => { + emit("download_progress", { + received: ev.total! + ev.loaded, + total: ev.total! * 2, + }); + }, + + responseType: "blob", + }); + + const fileName = url.split("/").pop()!; + const fileName2 = url2.split("/").pop()!; + + const dataUri = await toDataURI(resp.data); + const dataUri2 = await toDataURI(resp2.data); + + save(dataUri, fileName); + save(dataUri2, fileName2); +}; diff --git a/src/api/mocks/spaceDock.ts b/src/api/mocks/spaceDock.ts index b2e621c..a3f7b10 100644 --- a/src/api/mocks/spaceDock.ts +++ b/src/api/mocks/spaceDock.ts @@ -1,13 +1,13 @@ -import { SpaceDockAPI } from "../SpaceDock"; - -export const getMod = async (modId?: string) => { - const api = new SpaceDockAPI(); - - return await api.getMod(modId || ""); -}; - -export const getMods = async (page?: number, count?: number, gameId?: number) => { - const api = new SpaceDockAPI(); - - return gameId ? await api.getModsForGame(gameId, page, count) : await api.getMods(page, count); -}; +import { SpaceDockAPI } from "../SpaceDock"; + +export const getMod = async (modId?: string) => { + const api = new SpaceDockAPI(); + + return await api.getMod(modId || ""); +}; + +export const getMods = async (page?: number, count?: number, gameId?: number) => { + const api = new SpaceDockAPI(); + + return gameId ? await api.getModsForGame(gameId, page, count) : await api.getMods(page, count); +}; diff --git a/src/api/models/browse.ts b/src/api/models/browse.ts index a4d1cd2..81d151e 100644 --- a/src/api/models/browse.ts +++ b/src/api/models/browse.ts @@ -1,17 +1,17 @@ -import { BrowseModInfo, finishBrowseModInfo } from "./modinfo/browse"; - -export interface BrowseResult { - result: BrowseModInfo[]; - count: number; - pages: number; - page: number; -} - -export const finishBrowseResult = (data: Partial): BrowseResult => { - return { - result: data.result ? data.result.map((data) => finishBrowseModInfo(data)) : [], - count: data.count || 0, - pages: data.pages || 0, - page: data.page || 0, - }; -}; +import { BrowseModInfo, finishBrowseModInfo } from "./modinfo/browse"; + +export interface BrowseResult { + result: BrowseModInfo[]; + count: number; + pages: number; + page: number; +} + +export const finishBrowseResult = (data: Partial): BrowseResult => { + return { + result: data.result ? data.result.map((data) => finishBrowseModInfo(data)) : [], + count: data.count || 0, + pages: data.pages || 0, + page: data.page || 0, + }; +}; diff --git a/src/api/models/modinfo/browse.ts b/src/api/models/modinfo/browse.ts index 610c2e0..9cd77a6 100644 --- a/src/api/models/modinfo/browse.ts +++ b/src/api/models/modinfo/browse.ts @@ -1,52 +1,52 @@ -import { finishVersions, ModVersion } from "../versions"; - -export interface BrowseModInfo { - name: string; - id: number; - game: string; - game_id: number; - short_description: string; - downloads: number; - followers: number; - author: string; - default_version_id: number; - shared_authors: unknown[]; - background: string; - bg_offset_y: string; - license: string; - website: string; - donations: string; - source_code: string; - url: string; - versions: ModVersion[]; -} - -export interface ModWithDistance { - mod: BrowseModInfo; - dist: undefined; -} - -export const finishBrowseModInfo = (raw: Partial): BrowseModInfo => { - return { - name: raw.name || "", - id: raw.id || 0, - game: raw.game || "", - game_id: raw.game_id || 0, - short_description: raw.short_description || "", - downloads: raw.downloads || 0, - followers: raw.followers || 0, - author: raw.author || "", - default_version_id: raw.default_version_id || 0, - shared_authors: raw.shared_authors || [], - - background: raw.background || "https://spacedock.info/static/background-s.png", - - bg_offset_y: raw.bg_offset_y || "", - license: raw.license || "", - website: raw.website || "", - donations: raw.donations || "", - source_code: raw.source_code || "", - url: raw.url || "", - versions: raw.versions ? finishVersions(raw.versions) : [], - }; -}; +import { finishVersions, ModVersion } from "../versions"; + +export interface BrowseModInfo { + name: string; + id: number; + game: string; + game_id: number; + short_description: string; + downloads: number; + followers: number; + author: string; + default_version_id: number; + shared_authors: unknown[]; + background: string; + bg_offset_y: string; + license: string; + website: string; + donations: string; + source_code: string; + url: string; + versions: ModVersion[]; +} + +export interface ModWithDistance { + mod: BrowseModInfo; + dist: undefined; +} + +export const finishBrowseModInfo = (raw: Partial): BrowseModInfo => { + return { + name: raw.name || "", + id: raw.id || 0, + game: raw.game || "", + game_id: raw.game_id || 0, + short_description: raw.short_description || "", + downloads: raw.downloads || 0, + followers: raw.followers || 0, + author: raw.author || "", + default_version_id: raw.default_version_id || 0, + shared_authors: raw.shared_authors || [], + + background: raw.background || "https://spacedock.info/static/background-s.png", + + bg_offset_y: raw.bg_offset_y || "", + license: raw.license || "", + website: raw.website || "", + donations: raw.donations || "", + source_code: raw.source_code || "", + url: raw.url || "", + versions: raw.versions ? finishVersions(raw.versions) : [], + }; +}; diff --git a/src/api/models/modinfo/full.ts b/src/api/models/modinfo/full.ts index f634d67..3515d25 100644 --- a/src/api/models/modinfo/full.ts +++ b/src/api/models/modinfo/full.ts @@ -1,49 +1,49 @@ -import { finishVersions, ModVersion } from "../versions"; - -export interface FullModInfo { - name: string; - id: number; - game: string; - game_id: number; - short_description: string; - downloads: number; - followers: number; - author: string; - default_version_id: number; - shared_authors: unknown[]; - background: string; - bg_offset_y: string; - license: string; - website: string; - donations: string; - source_code: string; - url: string; - versions: ModVersion[]; - description: string; -} - -export const finishFullModInfo = (raw: Partial): FullModInfo => { - return { - name: raw.name || "", - id: raw.id || 0, - game: raw.game || "", - game_id: raw.game_id || 0, - short_description: raw.short_description || "", - downloads: raw.downloads || 0, - followers: raw.followers || 0, - author: raw.author || "", - default_version_id: raw.default_version_id || 0, - shared_authors: raw.shared_authors || [], - description: raw.description || "", - - background: raw.background || "https://spacedock.info/static/background.png", - - bg_offset_y: raw.bg_offset_y || "", - license: raw.license || "", - website: raw.website || "", - donations: raw.donations || "", - source_code: raw.source_code || "", - url: raw.url || "", - versions: raw.versions ? finishVersions(raw.versions) : [], - }; -}; +import { finishVersions, ModVersion } from "../versions"; + +export interface FullModInfo { + name: string; + id: number; + game: string; + game_id: number; + short_description: string; + downloads: number; + followers: number; + author: string; + default_version_id: number; + shared_authors: unknown[]; + background: string; + bg_offset_y: string; + license: string; + website: string; + donations: string; + source_code: string; + url: string; + versions: ModVersion[]; + description: string; +} + +export const finishFullModInfo = (raw: Partial): FullModInfo => { + return { + name: raw.name || "", + id: raw.id || 0, + game: raw.game || "", + game_id: raw.game_id || 0, + short_description: raw.short_description || "", + downloads: raw.downloads || 0, + followers: raw.followers || 0, + author: raw.author || "", + default_version_id: raw.default_version_id || 0, + shared_authors: raw.shared_authors || [], + description: raw.description || "", + + background: raw.background || "https://spacedock.info/static/background.png", + + bg_offset_y: raw.bg_offset_y || "", + license: raw.license || "", + website: raw.website || "", + donations: raw.donations || "", + source_code: raw.source_code || "", + url: raw.url || "", + versions: raw.versions ? finishVersions(raw.versions) : [], + }; +}; diff --git a/src/api/models/versions.ts b/src/api/models/versions.ts index ec8ce45..5f41178 100644 --- a/src/api/models/versions.ts +++ b/src/api/models/versions.ts @@ -1,21 +1,21 @@ -export interface ModVersion { - friendly_version: string; - game_version: string; - id: number; - created: string; - download_path: string; - changelog: string; - downloads: number; -} - -export const finishVersions = (raw: Partial[]): ModVersion[] => { - return raw.map((version) => ({ - friendly_version: version.friendly_version || "", - game_version: version.friendly_version || "", - id: version.id || 0, - created: version.created || "", - download_path: version.download_path || "", - changelog: version.changelog || "", - downloads: version.downloads || 0, - })); -}; +export interface ModVersion { + friendly_version: string; + game_version: string; + id: number; + created: string; + download_path: string; + changelog: string; + downloads: number; +} + +export const finishVersions = (raw: Partial[]): ModVersion[] => { + return raw.map((version) => ({ + friendly_version: version.friendly_version || "", + game_version: version.friendly_version || "", + id: version.id || 0, + created: version.created || "", + download_path: version.download_path || "", + changelog: version.changelog || "", + downloads: version.downloads || 0, + })); +}; diff --git a/src/api/setup.ts b/src/api/setup.ts index d6ec447..ec37ebf 100644 --- a/src/api/setup.ts +++ b/src/api/setup.ts @@ -1,15 +1,15 @@ -import { backend_boot } from "./boot"; -import { createMockAPI } from "./dev"; - -export const setup = async () => { - if (import.meta.env.TAURI_WEB_DEV) { - const eruda = (await import("eruda")).default; - - eruda.init(); - eruda.position({ x: 10, y: window.innerHeight - 45 }); - - createMockAPI(); - } - - await backend_boot(); -}; +import { backend_boot } from "./boot"; +import { createMockAPI } from "./dev"; + +export const setup = async () => { + if (import.meta.env.TAURI_WEB_DEV) { + const eruda = (await import("eruda")).default; + + eruda.init(); + eruda.position({ x: 10, y: window.innerHeight - 45 }); + + createMockAPI(); + } + + await backend_boot(); +}; diff --git a/src/app.d.ts b/src/app.d.ts index d221ad5..800c61f 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,10 +1,10 @@ -declare global { - export namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface Platform {} - } -} - -export {}; +declare global { + export namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface Platform {} + } +} + +export {}; diff --git a/src/app.html b/src/app.html index eced7a8..8ce2913 100644 --- a/src/app.html +++ b/src/app.html @@ -1,14 +1,14 @@ - - - - - - - - %sveltekit.head% - - - - %sveltekit.body% - - + + + + + + + + %sveltekit.head% + + + + %sveltekit.body% + + diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index e182a8a..a3d1578 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1 +1 @@ -export const ssr = false; +export const ssr = false; diff --git a/src/styles/_includes.scss b/src/styles/_includes.scss index 71c41be..ff28f27 100644 --- a/src/styles/_includes.scss +++ b/src/styles/_includes.scss @@ -1,14 +1,14 @@ -$fa-font-path: "@fortawesome/fontawesome-free/webfonts"; - -@import "@fortawesome/fontawesome-free/scss/fontawesome.scss"; -@import "@fortawesome/fontawesome-free/scss/regular.scss"; -@import "@fortawesome/fontawesome-free/scss/solid.scss"; -@import "@fortawesome/fontawesome-free/scss/brands.scss"; - -@import "@fontsource/ubuntu/index.css"; -@import "@fontsource/ubuntu-mono/index.css"; - -@font-face { - font-family: "manteka"; - src: url("../assets/manteka.otf"); -} +$fa-font-path: "@fortawesome/fontawesome-free/webfonts"; + +@import "@fortawesome/fontawesome-free/scss/fontawesome.scss"; +@import "@fortawesome/fontawesome-free/scss/regular.scss"; +@import "@fortawesome/fontawesome-free/scss/solid.scss"; +@import "@fortawesome/fontawesome-free/scss/brands.scss"; + +@import "@fontsource/ubuntu/index.css"; +@import "@fontsource/ubuntu-mono/index.css"; + +@font-face { + font-family: "manteka"; + src: url("../assets/manteka.otf"); +} diff --git a/src/styles/global.scss b/src/styles/global.scss index 2e7e80a..b46c721 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -1,29 +1,29 @@ -@import "includes"; - -::-webkit-scrollbar { - width: 8px; - margin: 0; -} - -::-webkit-scrollbar-track { - background-color: transparent; -} - -::-webkit-scrollbar-thumb { - background-color: #4c4c4c; - border-radius: 5px; -} - -html, -body { - width: 100%; - height: 100%; - - color: white; - font-family: "manteka", serif; - - margin: 0; - padding: 0; - - background-color: #1f2120; -} +@import "includes"; + +::-webkit-scrollbar { + width: 8px; + margin: 0; +} + +::-webkit-scrollbar-track { + background-color: transparent; +} + +::-webkit-scrollbar-thumb { + background-color: #4c4c4c; + border-radius: 5px; +} + +html, +body { + width: 100%; + height: 100%; + + color: white; + font-family: "manteka", serif; + + margin: 0; + padding: 0; + + background-color: #1f2120; +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 5be2e67..b06942e 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1,2 +1,2 @@ -/// -/// +/// +/// diff --git a/svelte.config.js b/svelte.config.js index 1d6a952..ddb509b 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,15 +1,15 @@ -// @ts-check - -import adapter from "@sveltejs/adapter-static"; -import { vitePreprocess } from "@sveltejs/kit/vite"; - -/** @type {import("@sveltejs/kit").Config} */ -export default { - preprocess: vitePreprocess(), - - kit: { - adapter: adapter({ - fallback: "index.html", - }), - }, -}; +// @ts-check + +import adapter from "@sveltejs/adapter-static"; +import { vitePreprocess } from "@sveltejs/kit/vite"; + +/** @type {import("@sveltejs/kit").Config} */ +export default { + preprocess: vitePreprocess(), + + kit: { + adapter: adapter({ + fallback: "index.html", + }), + }, +}; diff --git a/tsconfig.json b/tsconfig.json index 2413900..efe9867 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,29 +1,29 @@ -{ - "extends": "./.svelte-kit/tsconfig.json", - - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "alwaysStrict": true, - "declaration": true, - "esModuleInterop": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "lib": ["esnext", "DOM", "DOM.Iterable"], - "module": "esnext", - "moduleResolution": "node", - "strict": true, - "target": "esnext", - "noEmit": true, - "skipLibCheck": true, - "sourceMap": true, - "allowSyntheticDefaultImports": true, - "preserveValueImports": false - }, - - "ts-node": { - "esm": true - } -} +{ + "extends": "./.svelte-kit/tsconfig.json", + + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "lib": ["esnext", "DOM", "DOM.Iterable"], + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "target": "esnext", + "noEmit": true, + "skipLibCheck": true, + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "preserveValueImports": false + }, + + "ts-node": { + "esm": true + } +} diff --git a/vite.config.ts b/vite.config.ts index be26299..10bf984 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,46 +1,46 @@ -import { sveltekit } from "@sveltejs/kit/vite"; -import { defineConfig } from "vite"; - -export default defineConfig({ - clearScreen: false, - - plugins: [sveltekit()], - - server: { - port: process.env.TAURI_WEB_DEV ? 4000 : 1420, - strictPort: true, - cors: true, - - proxy: { - "^/_spacedock/.*": { - target: "https://spacedock.info/", - changeOrigin: true, - rewrite: (path) => path.replace(/^\/_spacedock/, ""), - followRedirects: true, - }, - }, - - hmr: process.env.TAURI_WEB_DEV - ? { - clientPort: 443, - port: 4000, - protocol: "wss", - } - : {}, - }, - - envPrefix: ["VITE_", "TAURI_"], - - resolve: { - alias: { - path: "path-browserify", - }, - }, - - build: { - target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13", - - minify: !process.env.TAURI_DEBUG ? "esbuild" : false, - sourcemap: !!process.env.TAURI_DEBUG, - }, -}); +import { sveltekit } from "@sveltejs/kit/vite"; +import { defineConfig } from "vite"; + +export default defineConfig({ + clearScreen: false, + + plugins: [sveltekit()], + + server: { + port: process.env.TAURI_WEB_DEV ? 4000 : 1420, + strictPort: true, + cors: true, + + proxy: { + "^/_spacedock/.*": { + target: "https://spacedock.info/", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/_spacedock/, ""), + followRedirects: true, + }, + }, + + hmr: process.env.TAURI_WEB_DEV + ? { + clientPort: 443, + port: 4000, + protocol: "wss", + } + : {}, + }, + + envPrefix: ["VITE_", "TAURI_"], + + resolve: { + alias: { + path: "path-browserify", + }, + }, + + build: { + target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13", + + minify: !process.env.TAURI_DEBUG ? "esbuild" : false, + sourcemap: !!process.env.TAURI_DEBUG, + }, +});