diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 0000000..28323e5 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,103 @@ +name: Setup environment + +inputs: + cargo-cache-key: + description: The key to cache cargo dependencies. Skips cargo caching if not provided. + required: false + cargo-cache-fallback-key: + description: The fallback key to use when caching cargo dependencies. Default to not using a fallback key. + required: false + cargo-cache-local-key: + description: The key to cache local cargo dependencies. Skips local cargo caching if not provided. + required: false + clippy: + description: Install Clippy if `true`. Defaults to `false`. + required: false + rustfmt: + description: Install Rustfmt if `true`. Defaults to `false`. + required: false + solana: + description: Install Solana if `true`. Defaults to `false`. + required: false + +runs: + using: 'composite' + steps: + - name: Setup pnpm + uses: pnpm/action-setup@v3 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'pnpm' + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + shell: bash + + - name: Set Environment Variables + shell: bash + run: pnpm zx ./scripts/ci/set-env.mjs + + - name: Install Rustfmt + if: ${{ inputs.rustfmt == 'true' }} + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.TOOLCHAIN_FORMAT }} + components: rustfmt + + - name: Install Clippy + if: ${{ inputs.clippy == 'true' }} + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.TOOLCHAIN_LINT }} + components: clippy + + - name: Install Solana + if: ${{ inputs.solana == 'true' }} + uses: metaplex-foundation/actions/install-solana@v1 + with: + version: ${{ env.SOLANA_VERSION }} + cache: true + + - name: Cache Cargo Dependencies + if: ${{ inputs.cargo-cache-key && !inputs.cargo-cache-fallback-key }} + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-${{ inputs.cargo-cache-key }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-${{ inputs.cargo-cache-key }} + + - name: Cache Cargo Dependencies With Fallback + if: ${{ inputs.cargo-cache-key && inputs.cargo-cache-fallback-key }} + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-${{ inputs.cargo-cache-key }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-${{ inputs.cargo-cache-key }} + ${{ runner.os }}-${{ inputs.cargo-cache-fallback-key }}-${{ hashFiles('**/Cargo.lock') }} + ${{ runner.os }}-${{ inputs.cargo-cache-fallback-key }} + + - name: Cache Local Cargo Dependencies + if: ${{ inputs.cargo-cache-local-key }} + uses: actions/cache@v4 + with: + path: | + .cargo/bin/ + .cargo/registry/index/ + .cargo/registry/cache/ + .cargo/git/db/ + key: ${{ runner.os }}-${{ inputs.cargo-cache-local-key }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-${{ inputs.cargo-cache-local-key }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..ae467f2 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,98 @@ +name: Main + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + format_and_lint_client_js: + name: Format & Lint Client JS + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + + - name: Format Client JS + run: pnpm clients:js:format + + - name: Lint Client JS + run: pnpm clients:js:lint + + format_and_lint_client_rust: + if: false # Disabled until we have a Rust client + name: Format & Lint Client Rust + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + clippy: true + rustfmt: true + + - name: Format Client Rust + run: pnpm clients:rust:format + + - name: Lint Client Rust + run: pnpm clients:rust:lint + + generate_clients: + name: Check Client Generation + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + rustfmt: true + + - name: Generate Clients + run: pnpm generate:clients + + - name: Check Working Directory + run: | + git status --porcelain + test -z "$(git status --porcelain)" + + test_client_js: + name: Test Client JS + runs-on: ubuntu-latest + needs: format_and_lint_client_js + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + solana: true + + - name: Test Client JS + run: pnpm clients:js:test + + test_client_rust: + if: false # Disabled until we have a Rust client + name: Test Client Rust + runs-on: ubuntu-latest + needs: format_and_lint_client_rust + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + cargo-cache-key: cargo-rust-client + solana: true + + - name: Test Client Rust + run: pnpm clients:rust:test diff --git a/.github/workflows/publish-js-client.yml b/.github/workflows/publish-js-client.yml new file mode 100644 index 0000000..fcb29c0 --- /dev/null +++ b/.github/workflows/publish-js-client.yml @@ -0,0 +1,95 @@ +name: Publish JS Client + +on: + workflow_dispatch: + inputs: + level: + description: Version level + required: true + default: patch + type: choice + options: + - patch + - minor + - major + - prerelease + - prepatch + - preminor + - premajor + tag: + description: NPM Tag (and preid for pre-releases) + required: true + type: string + default: latest + create_release: + description: Create a GitHub release + required: true + type: boolean + default: true + +jobs: + test_js: + name: Test JS client + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + solana: true + + - name: Format JS Client + run: pnpm clients:js:format + + - name: Lint JS Client + run: pnpm clients:js:lint + + - name: Test JS Client + run: pnpm clients:js:test + + publish_js: + name: Publish JS client + runs-on: ubuntu-latest + needs: test_js + permissions: + contents: write + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + + - name: Ensure NPM_TOKEN variable is set + env: + token: ${{ secrets.NPM_TOKEN }} + if: ${{ env.token == '' }} + run: | + echo "The NPM_TOKEN secret variable is not set" + echo "Go to \"Settings\" -> \"Secrets and variables\" -> \"Actions\" -> \"New repository secret\"." + exit 1 + + - name: NPM Authentication + run: pnpm config set '//registry.npmjs.org/:_authToken' "${NODE_AUTH_TOKEN}" + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Set Git Author + run: | + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + + - name: Publish JS Client + id: publish + run: pnpm clients:js:publish ${{ inputs.level }} ${{ inputs.tag }} + + - name: Push Commit and Tag + run: git push origin --follow-tags + + - name: Create GitHub release + if: github.event.inputs.create_release == 'true' + uses: ncipollo/release-action@v1 + with: + tag: js@v${{ steps.publish.outputs.new_version }} diff --git a/.github/workflows/publish-rust-client.yml b/.github/workflows/publish-rust-client.yml new file mode 100644 index 0000000..ee3f09d --- /dev/null +++ b/.github/workflows/publish-rust-client.yml @@ -0,0 +1,122 @@ +name: Publish Rust Client + +on: + workflow_dispatch: + inputs: + level: + description: Level + required: true + default: patch + type: choice + options: + - patch + - minor + - major + - rc + - beta + - alpha + - release + - version + version: + description: Version + required: false + type: string + dry_run: + description: Dry run + required: true + default: true + type: boolean + create_release: + description: Create a GitHub release + required: true + type: boolean + default: true + +jobs: + test_rust: + name: Test Rust client + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + cargo-cache-key: cargo-rust-client + clippy: true + rustfmt: true + solana: true + + - name: Format Rust Client + run: pnpm clients:rust:format + + - name: Lint Rust Client + run: pnpm clients:rust:lint + + - name: Test Rust Client + run: pnpm clients:rust:test + + publish_rust: + name: Publish Rust Client + runs-on: ubuntu-latest + needs: test_rust + permissions: + contents: write + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + cargo-cache-key: cargo-publish-rust-client + cargo-cache-fallback-key: cargo-rust-client + clippy: true + rustfmt: true + + - name: Install Cargo Release + run: which cargo-release || cargo install cargo-release + + - name: Ensure CARGO_REGISTRY_TOKEN variable is set + env: + token: ${{ secrets.CARGO_REGISTRY_TOKEN }} + if: ${{ env.token == '' }} + run: | + echo "The CARGO_REGISTRY_TOKEN secret variable is not set" + echo "Go to \"Settings\" -> \"Secrets and variables\" -> \"Actions\" -> \"New repository secret\"." + exit 1 + + - name: Set Git Author + run: | + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + + - name: Publish Rust Client + id: publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + run: | + if [ "${{ inputs.level }}" == "version" ]; then + LEVEL=${{ inputs.version }} + else + LEVEL=${{ inputs.level }} + fi + + if [ "${{ inputs.dry_run }}" == "true" ]; then + OPTIONS="--dry-run" + else + OPTIONS="" + fi + + pnpm clients:rust:publish $LEVEL $OPTIONS + + - name: Push Commit and Tag + if: github.event.inputs.dry_run != 'true' + run: git push origin --follow-tags + + - name: Create GitHub release + if: github.event.inputs.create_release == 'true' && github.event.inputs.dry_run != 'true' + uses: ncipollo/release-action@v1 + with: + tag: rust@v${{ steps.publish.outputs.new_version }} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..254c729 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "useTabs": false, + "tabWidth": 2, + "arrowParens": "always", + "printWidth": 80 +} diff --git a/Cargo.toml b/Cargo.toml index ffc89ba..62b16bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,12 @@ [workspace] resolver = "2" members = ["clients/rust"] + +[workspace.metadata.cli] +solana = "1.18.18" + +# Specify Rust toolchains for rustfmt, clippy, and build. +# Any unprovided toolchains default to stable. +[workspace.metadata.toolchains] +format = "1.78.0" +lint = "1.78.0" diff --git a/README.md b/README.md index 0497713..2103016 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Token 2022 - - + diff --git a/clients/js/package.json b/clients/js/package.json index b671c95..a2fca7f 100644 --- a/clients/js/package.json +++ b/clients/js/package.json @@ -49,12 +49,15 @@ "eslint": "^8.57.0", "prettier": "^3.3.3", "rimraf": "^5.0.5", - "tsup": "^8.0.2", + "tsup": "^8.1.2", "typedoc": "^0.25.12", "typedoc-plugin-missing-exports": "^2.2.0", "typescript": "^5.5.3" }, "ava": { + "nodeArguments": [ + "--no-warnings" + ], "require": [ "@solana/webcrypto-ed25519-polyfill" ], diff --git a/clients/js/pnpm-lock.yaml b/clients/js/pnpm-lock.yaml index e34d49d..313ef30 100644 --- a/clients/js/pnpm-lock.yaml +++ b/clients/js/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^5.0.5 version: 5.0.5 tsup: - specifier: ^8.0.2 - version: 8.0.2(typescript@5.5.3) + specifier: ^8.1.2 + version: 8.2.3(typescript@5.5.3)(yaml@2.4.2) typedoc: specifier: ^0.25.12 version: 0.25.13(typescript@5.5.3) @@ -63,141 +63,147 @@ packages: resolution: {integrity: sha512-1iWZQ/nr9iflhLK9VN8H+1oDZqe93qxNnyYUz+jTzkYPAHc5fdZXBrqmNIgIfFhWYXK5OaQ5YtC7OmLeTNhVEg==} engines: {node: ^14.19 || ^16.15 || ^18 || ^20} - '@esbuild/aix-ppc64@0.19.12': - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} - engines: {node: '>=12'} + '@esbuild/aix-ppc64@0.23.0': + resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.19.12': - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} - engines: {node: '>=12'} + '@esbuild/android-arm64@0.23.0': + resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.19.12': - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.23.0': + resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==} + engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.19.12': - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.23.0': + resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==} + engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.19.12': - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.23.0': + resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.19.12': - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.23.0': + resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.19.12': - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.23.0': + resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.19.12': - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.23.0': + resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.19.12': - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.23.0': + resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.19.12': - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.23.0': + resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.19.12': - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.23.0': + resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.19.12': - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.23.0': + resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.19.12': - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.23.0': + resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.19.12': - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.23.0': + resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.19.12': - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.23.0': + resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.19.12': - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.23.0': + resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.19.12': - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.23.0': + resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-x64@0.19.12': - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} - engines: {node: '>=12'} + '@esbuild/netbsd-x64@0.23.0': + resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-x64@0.19.12': - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} - engines: {node: '>=12'} + '@esbuild/openbsd-arm64@0.23.0': + resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.0': + resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.19.12': - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} - engines: {node: '>=12'} + '@esbuild/sunos-x64@0.23.0': + resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.19.12': - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.23.0': + resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.19.12': - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.23.0': + resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.19.12': - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} - engines: {node: '>=12'} + '@esbuild/win32-x64@0.23.0': + resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==} + engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -279,83 +285,83 @@ packages: resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'} - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.19.1': + resolution: {integrity: sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.19.1': + resolution: {integrity: sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.19.1': + resolution: {integrity: sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.19.1': + resolution: {integrity: sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.19.1': + resolution: {integrity: sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.19.1': + resolution: {integrity: sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.19.1': + resolution: {integrity: sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.19.1': + resolution: {integrity: sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.19.1': + resolution: {integrity: sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.19.1': + resolution: {integrity: sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.19.1': + resolution: {integrity: sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.19.1': + resolution: {integrity: sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.19.1': + resolution: {integrity: sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.19.1': + resolution: {integrity: sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.19.1': + resolution: {integrity: sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.19.1': + resolution: {integrity: sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==} cpu: [x64] os: [win32] @@ -791,11 +797,11 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - bundle-require@4.1.0: - resolution: {integrity: sha512-FeArRFM+ziGkRViKRnSTbHZc35dgmR9yNog05Kn0+ItI59pOAISGvnnIwW1WgFZQW59IxD9QpJnUPkdIPfZuXg==} + bundle-require@5.0.0: + resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: - esbuild: '>=0.17' + esbuild: '>=0.18' cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} @@ -880,6 +886,10 @@ packages: resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'} + consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} @@ -908,6 +918,15 @@ packages: supports-color: optional: true + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -942,9 +961,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} - engines: {node: '>=12'} + esbuild@0.23.0: + resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==} + engines: {node: '>=18'} hasBin: true escalade@3.1.2: @@ -1555,6 +1574,9 @@ packages: resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} engines: {node: '>=12'} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -1571,16 +1593,22 @@ packages: resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} peerDependencies: + jiti: '>=1.21.0' postcss: '>=8.0.9' - ts-node: '>=9.0.0' + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: + jiti: + optional: true postcss: optional: true - ts-node: + tsx: + optional: true + yaml: optional: true prelude-ls@1.2.1: @@ -1644,8 +1672,8 @@ packages: engines: {node: '>=14'} hasBin: true - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.19.1: + resolution: {integrity: sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -1808,8 +1836,8 @@ packages: tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tsup@8.0.2: - resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==} + tsup@8.2.3: + resolution: {integrity: sha512-6YNT44oUfXRbZuSMNmN36GzwPPIlD2wBccY7looM2fkTcxkf2NEmwr3OZuDZoySklnrIG4hoEtzy8yUXYOqNcg==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -1970,73 +1998,76 @@ snapshots: escape-string-regexp: 5.0.0 execa: 7.2.0 - '@esbuild/aix-ppc64@0.19.12': + '@esbuild/aix-ppc64@0.23.0': + optional: true + + '@esbuild/android-arm64@0.23.0': optional: true - '@esbuild/android-arm64@0.19.12': + '@esbuild/android-arm@0.23.0': optional: true - '@esbuild/android-arm@0.19.12': + '@esbuild/android-x64@0.23.0': optional: true - '@esbuild/android-x64@0.19.12': + '@esbuild/darwin-arm64@0.23.0': optional: true - '@esbuild/darwin-arm64@0.19.12': + '@esbuild/darwin-x64@0.23.0': optional: true - '@esbuild/darwin-x64@0.19.12': + '@esbuild/freebsd-arm64@0.23.0': optional: true - '@esbuild/freebsd-arm64@0.19.12': + '@esbuild/freebsd-x64@0.23.0': optional: true - '@esbuild/freebsd-x64@0.19.12': + '@esbuild/linux-arm64@0.23.0': optional: true - '@esbuild/linux-arm64@0.19.12': + '@esbuild/linux-arm@0.23.0': optional: true - '@esbuild/linux-arm@0.19.12': + '@esbuild/linux-ia32@0.23.0': optional: true - '@esbuild/linux-ia32@0.19.12': + '@esbuild/linux-loong64@0.23.0': optional: true - '@esbuild/linux-loong64@0.19.12': + '@esbuild/linux-mips64el@0.23.0': optional: true - '@esbuild/linux-mips64el@0.19.12': + '@esbuild/linux-ppc64@0.23.0': optional: true - '@esbuild/linux-ppc64@0.19.12': + '@esbuild/linux-riscv64@0.23.0': optional: true - '@esbuild/linux-riscv64@0.19.12': + '@esbuild/linux-s390x@0.23.0': optional: true - '@esbuild/linux-s390x@0.19.12': + '@esbuild/linux-x64@0.23.0': optional: true - '@esbuild/linux-x64@0.19.12': + '@esbuild/netbsd-x64@0.23.0': optional: true - '@esbuild/netbsd-x64@0.19.12': + '@esbuild/openbsd-arm64@0.23.0': optional: true - '@esbuild/openbsd-x64@0.19.12': + '@esbuild/openbsd-x64@0.23.0': optional: true - '@esbuild/sunos-x64@0.19.12': + '@esbuild/sunos-x64@0.23.0': optional: true - '@esbuild/win32-arm64@0.19.12': + '@esbuild/win32-arm64@0.23.0': optional: true - '@esbuild/win32-ia32@0.19.12': + '@esbuild/win32-ia32@0.23.0': optional: true - '@esbuild/win32-x64@0.19.12': + '@esbuild/win32-x64@0.23.0': optional: true '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': @@ -2137,52 +2168,52 @@ snapshots: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.19.1': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.19.1': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.19.1': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.19.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.19.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.19.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.19.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.19.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.19.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.19.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.19.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.19.1': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.19.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.19.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.19.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.19.1': optional: true '@sindresorhus/merge-streams@2.3.0': {} @@ -2834,9 +2865,9 @@ snapshots: dependencies: fill-range: 7.0.1 - bundle-require@4.1.0(esbuild@0.19.12): + bundle-require@5.0.0(esbuild@0.23.0): dependencies: - esbuild: 0.19.12 + esbuild: 0.23.0 load-tsconfig: 0.2.5 cac@6.7.14: {} @@ -2918,6 +2949,8 @@ snapshots: semver: 7.6.1 well-known-symbols: 2.0.0 + consola@3.2.3: {} + console-control-strings@1.1.0: {} convert-to-spaces@2.0.1: {} @@ -2940,6 +2973,10 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.3.6: + dependencies: + ms: 2.1.2 + deep-is@0.1.4: {} delegates@1.0.0: {} @@ -2964,31 +3001,32 @@ snapshots: emoji-regex@9.2.2: {} - esbuild@0.19.12: + esbuild@0.23.0: optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 + '@esbuild/aix-ppc64': 0.23.0 + '@esbuild/android-arm': 0.23.0 + '@esbuild/android-arm64': 0.23.0 + '@esbuild/android-x64': 0.23.0 + '@esbuild/darwin-arm64': 0.23.0 + '@esbuild/darwin-x64': 0.23.0 + '@esbuild/freebsd-arm64': 0.23.0 + '@esbuild/freebsd-x64': 0.23.0 + '@esbuild/linux-arm': 0.23.0 + '@esbuild/linux-arm64': 0.23.0 + '@esbuild/linux-ia32': 0.23.0 + '@esbuild/linux-loong64': 0.23.0 + '@esbuild/linux-mips64el': 0.23.0 + '@esbuild/linux-ppc64': 0.23.0 + '@esbuild/linux-riscv64': 0.23.0 + '@esbuild/linux-s390x': 0.23.0 + '@esbuild/linux-x64': 0.23.0 + '@esbuild/netbsd-x64': 0.23.0 + '@esbuild/openbsd-arm64': 0.23.0 + '@esbuild/openbsd-x64': 0.23.0 + '@esbuild/sunos-x64': 0.23.0 + '@esbuild/win32-arm64': 0.23.0 + '@esbuild/win32-ia32': 0.23.0 + '@esbuild/win32-x64': 0.23.0 escalade@3.1.2: {} @@ -3566,6 +3604,8 @@ snapshots: path-type@5.0.0: {} + picocolors@1.0.1: {} + picomatch@2.3.1: {} picomatch@3.0.1: {} @@ -3576,9 +3616,10 @@ snapshots: dependencies: irregular-plurals: 3.5.0 - postcss-load-config@4.0.2: + postcss-load-config@6.0.1(yaml@2.4.2): dependencies: lilconfig: 3.1.1 + optionalDependencies: yaml: 2.4.2 prelude-ls@1.2.1: {} @@ -3625,26 +3666,26 @@ snapshots: dependencies: glob: 10.3.12 - rollup@4.17.2: + rollup@4.19.1: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.19.1 + '@rollup/rollup-android-arm64': 4.19.1 + '@rollup/rollup-darwin-arm64': 4.19.1 + '@rollup/rollup-darwin-x64': 4.19.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.19.1 + '@rollup/rollup-linux-arm-musleabihf': 4.19.1 + '@rollup/rollup-linux-arm64-gnu': 4.19.1 + '@rollup/rollup-linux-arm64-musl': 4.19.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.19.1 + '@rollup/rollup-linux-riscv64-gnu': 4.19.1 + '@rollup/rollup-linux-s390x-gnu': 4.19.1 + '@rollup/rollup-linux-x64-gnu': 4.19.1 + '@rollup/rollup-linux-x64-musl': 4.19.1 + '@rollup/rollup-win32-arm64-msvc': 4.19.1 + '@rollup/rollup-win32-ia32-msvc': 4.19.1 + '@rollup/rollup-win32-x64-msvc': 4.19.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -3799,27 +3840,31 @@ snapshots: tslib@1.14.1: {} - tsup@8.0.2(typescript@5.5.3): + tsup@8.2.3(typescript@5.5.3)(yaml@2.4.2): dependencies: - bundle-require: 4.1.0(esbuild@0.19.12) + bundle-require: 5.0.0(esbuild@0.23.0) cac: 6.7.14 chokidar: 3.6.0 - debug: 4.3.4 - esbuild: 0.19.12 + consola: 3.2.3 + debug: 4.3.6 + esbuild: 0.23.0 execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2 + picocolors: 1.0.1 + postcss-load-config: 6.0.1(yaml@2.4.2) resolve-from: 5.0.0 - rollup: 4.17.2 + rollup: 4.19.1 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: + - jiti - supports-color - - ts-node + - tsx + - yaml tsutils@3.21.0(typescript@5.5.3): dependencies: @@ -3916,7 +3961,8 @@ snapshots: yallist@4.0.0: {} - yaml@2.4.2: {} + yaml@2.4.2: + optional: true yargs-parser@21.1.1: {} diff --git a/clients/js/src/generated/errors/associatedToken.ts b/clients/js/src/generated/errors/associatedToken.ts index 25a8659..9c00376 100644 --- a/clients/js/src/generated/errors/associatedToken.ts +++ b/clients/js/src/generated/errors/associatedToken.ts @@ -6,6 +6,14 @@ * @see https://github.com/kinobi-so/kinobi */ +import { + isProgramError, + type Address, + type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM, + type SolanaError, +} from '@solana/web3.js'; +import { ASSOCIATED_TOKEN_PROGRAM_ADDRESS } from '../programs'; + /** InvalidOwner: Associated token account owner does not match address derivation */ export const ASSOCIATED_TOKEN_ERROR__INVALID_OWNER = 0x0; // 0 @@ -31,3 +39,21 @@ export function getAssociatedTokenErrorMessage( return 'Error message not available in production bundles.'; } + +export function isAssociatedTokenError< + TProgramErrorCode extends AssociatedTokenError, +>( + error: unknown, + transactionMessage: { + instructions: Record; + }, + code?: TProgramErrorCode +): error is SolanaError & + Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> { + return isProgramError( + error, + transactionMessage, + ASSOCIATED_TOKEN_PROGRAM_ADDRESS, + code + ); +} diff --git a/clients/js/src/generated/errors/token2022.ts b/clients/js/src/generated/errors/token2022.ts index 5c7f667..b749420 100644 --- a/clients/js/src/generated/errors/token2022.ts +++ b/clients/js/src/generated/errors/token2022.ts @@ -6,6 +6,14 @@ * @see https://github.com/kinobi-so/kinobi */ +import { + isProgramError, + type Address, + type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM, + type SolanaError, +} from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ADDRESS } from '../programs'; + /** NotRentExempt: Lamport balance below rent-exempt threshold */ export const TOKEN_2022_ERROR__NOT_RENT_EXEMPT = 0x0; // 0 /** InsufficientFunds: Insufficient funds */ @@ -102,3 +110,19 @@ export function getToken2022ErrorMessage(code: Token2022Error): string { return 'Error message not available in production bundles.'; } + +export function isToken2022Error( + error: unknown, + transactionMessage: { + instructions: Record; + }, + code?: TProgramErrorCode +): error is SolanaError & + Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> { + return isProgramError( + error, + transactionMessage, + TOKEN_2022_PROGRAM_ADDRESS, + code + ); +} diff --git a/clients/js/src/generated/programs/associatedToken.ts b/clients/js/src/generated/programs/associatedToken.ts index 5fe5413..c3d3847 100644 --- a/clients/js/src/generated/programs/associatedToken.ts +++ b/clients/js/src/generated/programs/associatedToken.ts @@ -6,7 +6,12 @@ * @see https://github.com/kinobi-so/kinobi */ -import { containsBytes, getU8Encoder, type Address } from '@solana/web3.js'; +import { + containsBytes, + getU8Encoder, + type Address, + type ReadonlyUint8Array, +} from '@solana/web3.js'; import { type ParsedCreateAssociatedTokenIdempotentInstruction, type ParsedCreateAssociatedTokenInstruction, @@ -23,10 +28,9 @@ export enum AssociatedTokenInstruction { } export function identifyAssociatedTokenInstruction( - instruction: { data: Uint8Array } | Uint8Array + instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array ): AssociatedTokenInstruction { - const data = - instruction instanceof Uint8Array ? instruction : instruction.data; + const data = 'data' in instruction ? instruction.data : instruction; if (containsBytes(data, getU8Encoder().encode(0), 0)) { return AssociatedTokenInstruction.CreateAssociatedToken; } diff --git a/clients/js/src/generated/programs/token2022.ts b/clients/js/src/generated/programs/token2022.ts index 9d8713b..8c5ba43 100644 --- a/clients/js/src/generated/programs/token2022.ts +++ b/clients/js/src/generated/programs/token2022.ts @@ -6,7 +6,12 @@ * @see https://github.com/kinobi-so/kinobi */ -import { containsBytes, getU8Encoder, type Address } from '@solana/web3.js'; +import { + containsBytes, + getU8Encoder, + type Address, + type ReadonlyUint8Array, +} from '@solana/web3.js'; import { type ParsedAmountToUiAmountInstruction, type ParsedApproveCheckedInstruction, @@ -45,9 +50,9 @@ export enum Token2022Account { } export function identifyToken2022Account( - account: { data: Uint8Array } | Uint8Array + account: { data: ReadonlyUint8Array } | ReadonlyUint8Array ): Token2022Account { - const data = account instanceof Uint8Array ? account : account.data; + const data = 'data' in account ? account.data : account; if (data.length === 82) { return Token2022Account.Mint; } @@ -91,10 +96,9 @@ export enum Token2022Instruction { } export function identifyToken2022Instruction( - instruction: { data: Uint8Array } | Uint8Array + instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array ): Token2022Instruction { - const data = - instruction instanceof Uint8Array ? instruction : instruction.data; + const data = 'data' in instruction ? instruction.data : instruction; if (containsBytes(data, getU8Encoder().encode(0), 0)) { return Token2022Instruction.InitializeMint; } diff --git a/clients/rust/Cargo.toml b/clients/rust/Cargo.toml index 44af11a..7162de9 100644 --- a/clients/rust/Cargo.toml +++ b/clients/rust/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "spl-token-2022-client" version = "0.0.0" +description = "A generated Rust library for the Token 2022 program" +repository = "https://github.com/solana-program/token-2022" edition = "2021" readme = "README.md" license-file = "../../LICENSE" diff --git a/package.json b/package.json index 7ac195a..73e174d 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,28 @@ { "private": true, "scripts": { + "solana:check": "zx ./scripts/check-solana-version.mjs", + "solana:link": "zx ./scripts/link-solana-version.mjs", "generate": "pnpm generate:clients", "generate:clients": "zx ./scripts/generate-clients.mjs", "validator:start": "zx ./scripts/start-validator.mjs", "validator:restart": "pnpm validator:start --restart", "validator:stop": "zx ./scripts/stop-validator.mjs", + "clients:js:format": "zx ./scripts/client/format-js.mjs", + "clients:js:lint": "zx ./scripts/client/lint-js.mjs", + "clients:js:publish": "zx ./scripts/client/publish-js.mjs", "clients:js:test": "zx ./scripts/client/test-js.mjs", - "clients:rust:test": "zx ./scripts/client/test-rust.mjs" + "clients:rust:format": "zx ./scripts/client/format-rust.mjs", + "clients:rust:lint": "zx ./scripts/client/lint-rust.mjs", + "clients:rust:publish": "zx ./scripts/client/publish-rust.mjs", + "clients:rust:test": "zx ./scripts/client/test-rust.mjs", + "template:upgrade": "zx ./scripts/upgrade-template.mjs" }, "devDependencies": { "@iarna/toml": "^2.2.5", - "kinobi": "^0.21.0", - "@kinobi-so/renderers-js": "^0.21.0", + "@kinobi-so/renderers-js": "^0.21.2", "@kinobi-so/renderers-rust": "^0.21.0", + "kinobi": "^0.21.0", "typescript": "^5.5.2", "zx": "^7.2.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a5e1ed..c833f9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^2.2.5 version: 2.2.5 '@kinobi-so/renderers-js': - specifier: ^0.21.0 - version: 0.21.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) + specifier: ^0.21.2 + version: 0.21.2(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@kinobi-so/renderers-rust': specifier: ^0.21.0 version: 0.21.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) @@ -48,8 +48,8 @@ packages: '@kinobi-so/renderers-core@0.20.7': resolution: {integrity: sha512-KJhU8+UMowO9dDkLhEodAkbRkgSxdfBWeY+DIgOCgXcakt0T140K7OREuaAo9fp12Owf+10SAEGx9AzTNySoHA==} - '@kinobi-so/renderers-js@0.21.0': - resolution: {integrity: sha512-KjYU9BB8U2O9u2FZD+CIoMHgt6dSqO+cwDGIjCaH/GIsiKU5WDfO2IuBSoDWTO37icSVbzM2NeHyW3+RfUyYDg==} + '@kinobi-so/renderers-js@0.21.2': + resolution: {integrity: sha512-G576GAQ10ugmA63EZRlEbv892th37q9ow+AMzZD1vtypRCEJ7znakzySSDG3aeqaZujk2igKXFQTD+FHuY/xPg==} '@kinobi-so/renderers-rust@0.21.0': resolution: {integrity: sha512-BLe1SW6XFBhjtZdCc7cuukMWrJTbhCafCCmXryLmjzF7jaiK9nyZZFinHxljSac4HCk2vDn22mHAwOjabaDQ2Q==} @@ -432,7 +432,7 @@ snapshots: '@kinobi-so/nodes': 0.21.0 '@kinobi-so/visitors-core': 0.21.0 - '@kinobi-so/renderers-js@0.21.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3)': + '@kinobi-so/renderers-js@0.21.2(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3)': dependencies: '@kinobi-so/errors': 0.21.0 '@kinobi-so/nodes': 0.21.0 diff --git a/scripts/check-solana-version.mjs b/scripts/check-solana-version.mjs new file mode 100644 index 0000000..f0844be --- /dev/null +++ b/scripts/check-solana-version.mjs @@ -0,0 +1,18 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mjs'; + +const expectedVersion = getSolanaVersion(); +const installedVersion = await getInstalledSolanaVersion(); + +if (installedVersion !== expectedVersion) { + echo( + chalk.yellow('[ WARNING ]'), + `The installed Solana version ${installedVersion} does not match the expected version ${expectedVersion}.` + ); +} else { + echo( + chalk.green('[ SUCCESS ]'), + `The expected Solana version ${expectedVersion} is installed.` + ); +} diff --git a/scripts/ci/set-env.mjs b/scripts/ci/set-env.mjs new file mode 100644 index 0000000..276d37b --- /dev/null +++ b/scripts/ci/set-env.mjs @@ -0,0 +1,6 @@ +#!/usr/bin/env zx +import { getSolanaVersion, getToolchain } from '../utils.mjs'; + +await $`echo "SOLANA_VERSION=${getSolanaVersion()}" >> $GITHUB_ENV`; +await $`echo "TOOLCHAIN_FORMAT=${getToolchain('format')}" >> $GITHUB_ENV`; +await $`echo "TOOLCHAIN_LINT=${getToolchain('lint')}" >> $GITHUB_ENV`; diff --git a/scripts/client/format-js.mjs b/scripts/client/format-js.mjs new file mode 100644 index 0000000..dcfc3d4 --- /dev/null +++ b/scripts/client/format-js.mjs @@ -0,0 +1,8 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { cliArguments, workingDirectory } from '../utils.mjs'; + +// Format the client using Prettier. +cd(path.join(workingDirectory, 'clients', 'js')); +await $`pnpm install`; +await $`pnpm format ${cliArguments()}`; diff --git a/scripts/client/format-rust.mjs b/scripts/client/format-rust.mjs new file mode 100644 index 0000000..038a832 --- /dev/null +++ b/scripts/client/format-rust.mjs @@ -0,0 +1,30 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { + cliArguments, + getToolchainArgument, + partitionArguments, + popArgument, + workingDirectory, +} from '../utils.mjs'; + +// Configure additional arguments here, e.g.: +// ['--arg1', '--arg2', ...cliArguments()] +const formatArgs = cliArguments(); + +const fix = popArgument(formatArgs, '--fix'); +const [cargoArgs, fmtArgs] = partitionArguments(formatArgs, '--'); +const toolchain = getToolchainArgument('format'); +const manifestPath = path.join( + workingDirectory, + 'clients', + 'rust', + 'Cargo.toml' +); + +// Format the client. +if (fix) { + await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- ${fmtArgs}`; +} else { + await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- --check ${fmtArgs}`; +} diff --git a/scripts/client/lint-js.mjs b/scripts/client/lint-js.mjs new file mode 100644 index 0000000..f5583e2 --- /dev/null +++ b/scripts/client/lint-js.mjs @@ -0,0 +1,8 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { cliArguments, workingDirectory } from '../utils.mjs'; + +// Check the client using ESLint. +cd(path.join(workingDirectory, 'clients', 'js')); +await $`pnpm install`; +await $`pnpm lint ${cliArguments()}`; diff --git a/scripts/client/lint-rust.mjs b/scripts/client/lint-rust.mjs new file mode 100644 index 0000000..4cb46bf --- /dev/null +++ b/scripts/client/lint-rust.mjs @@ -0,0 +1,28 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { + cliArguments, + getToolchainArgument, + popArgument, + workingDirectory, +} from '../utils.mjs'; + +// Configure additional arguments here, e.g.: +// ['--arg1', '--arg2', ...cliArguments()] +const lintArgs = cliArguments(); + +const fix = popArgument(lintArgs, '--fix'); +const toolchain = getToolchainArgument('format'); +const manifestPath = path.join( + workingDirectory, + 'clients', + 'rust', + 'Cargo.toml' +); + +// Check the client using Clippy. +if (fix) { + await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} --fix ${lintArgs}`; +} else { + await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${lintArgs}`; +} diff --git a/scripts/client/publish-js.mjs b/scripts/client/publish-js.mjs new file mode 100644 index 0000000..51df188 --- /dev/null +++ b/scripts/client/publish-js.mjs @@ -0,0 +1,35 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { cliArguments, workingDirectory } from '../utils.mjs'; + +const [level, tag = 'latest'] = cliArguments(); +if (!level) { + throw new Error('A version level — e.g. "path" — must be provided.'); +} + +// Go to the client directory and install the dependencies. +cd(path.join(workingDirectory, 'clients', 'js')); +await $`pnpm install`; + +// Update the version. +const versionArgs = [ + '--no-git-tag-version', + ...(level.startsWith('pre') ? [`--preid ${tag}`] : []), +]; +let { stdout } = await $`pnpm version ${level} ${versionArgs}`; +const newVersion = stdout.slice(1).trim(); + +// Expose the new version to CI if needed. +if (process.env.CI) { + await $`echo "new_version=${newVersion}" >> $GITHUB_OUTPUT`; +} + +// Publish the package. +// This will also build the package before publishing (see prepublishOnly script). +await $`pnpm publish --no-git-checks --tag ${tag}`; + +// Commit the new version. +await $`git commit -am "Publish JS client v${newVersion}"`; + +// Tag the new version. +await $`git tag -a js@v${newVersion} -m "JS client v${newVersion}"`; diff --git a/scripts/client/publish-rust.mjs b/scripts/client/publish-rust.mjs new file mode 100644 index 0000000..b7a9fa6 --- /dev/null +++ b/scripts/client/publish-rust.mjs @@ -0,0 +1,40 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { cliArguments, getCargo, workingDirectory } from '../utils.mjs'; + +const dryRun = argv['dry-run'] ?? false; +const [level] = cliArguments(); +if (!level) { + throw new Error('A version level — e.g. "path" — must be provided.'); +} + +// Go to the client directory and install the dependencies. +cd(path.join(workingDirectory, 'clients', 'rust')); + +// Publish the new version. +const releaseArgs = dryRun + ? [] + : ['--no-push', '--no-tag', '--no-confirm', '--execute']; +await $`cargo release ${level} ${releaseArgs}`; + +// Stop here if this is a dry run. +if (dryRun) { + process.exit(0); +} + +// Get the new version. +const newVersion = getCargo(path.join('clients', 'rust')).package.version; + +// Expose the new version to CI if needed. +if (process.env.CI) { + await $`echo "new_version=${newVersion}" >> $GITHUB_OUTPUT`; +} + +// Soft reset the last commit so we can create our own commit and tag. +await $`git reset --soft HEAD~1`; + +// Commit the new version. +await $`git commit -am "Publish Rust client v${newVersion}"`; + +// Tag the new version. +await $`git tag -a rust@v${newVersion} -m "Rust client v${newVersion}"`; diff --git a/scripts/client/test-js.mjs b/scripts/client/test-js.mjs index 59668ab..652df0e 100644 --- a/scripts/client/test-js.mjs +++ b/scripts/client/test-js.mjs @@ -1,12 +1,12 @@ #!/usr/bin/env zx import 'zx/globals'; -import { workingDirectory } from '../utils.mjs'; +import { cliArguments, workingDirectory } from '../utils.mjs'; -// Start the local validator if it's not already running. +// Start the local validator, or restart it if it is already running. await $`pnpm validator:restart`; // Build the client and run the tests. cd(path.join(workingDirectory, 'clients', 'js')); await $`pnpm install`; await $`pnpm build`; -await $`pnpm test ${argv._}`; +await $`pnpm test ${cliArguments()}`; diff --git a/scripts/client/test-rust.mjs b/scripts/client/test-rust.mjs index e5c736e..48e2a30 100644 --- a/scripts/client/test-rust.mjs +++ b/scripts/client/test-rust.mjs @@ -1,12 +1,17 @@ #!/usr/bin/env zx import 'zx/globals'; -import { workingDirectory } from '../utils.mjs'; +import { cliArguments, workingDirectory } from '../utils.mjs'; + +// Configure additional arguments here, e.g.: +// ['--arg1', '--arg2', ...cliArguments()] +const testArgs = cliArguments(); + +const hasSolfmt = await which('solfmt', { nothrow: true }); // Run the tests. cd(path.join(workingDirectory, 'clients', 'rust')); -const hasSolfmt = await which('solfmt', { nothrow: true }); if (hasSolfmt) { - await $`cargo test-sbf ${argv._} 2>&1 | solfmt`; + await $`cargo test-sbf ${testArgs} 2>&1 | solfmt`; } else { - await $`cargo test-sbf ${argv._}`; + await $`cargo test-sbf ${testArgs}`; } diff --git a/scripts/generate-clients.mjs b/scripts/generate-clients.mjs index d222b90..80bb37b 100644 --- a/scripts/generate-clients.mjs +++ b/scripts/generate-clients.mjs @@ -1,20 +1,20 @@ #!/usr/bin/env zx -import "zx/globals"; -import { createFromRoot } from "kinobi"; -import { renderVisitor as renderJavaScriptVisitor } from "@kinobi-so/renderers-js"; +import 'zx/globals'; +import { createFromRoot } from 'kinobi'; +import { renderVisitor as renderJavaScriptVisitor } from '@kinobi-so/renderers-js'; // import { renderVisitor as renderRustVisitor } from "@kinobi-so/renderers-rust"; -import { workingDirectory } from "./utils.mjs"; +import { workingDirectory } from './utils.mjs'; // Instanciate Kinobi. const kinobi = createFromRoot( - require(path.join(workingDirectory, "program", "idl.json")) + require(path.join(workingDirectory, 'program', 'idl.json')) ); // Render JavaScript. -const jsClient = path.join(__dirname, "..", "clients", "js"); +const jsClient = path.join(__dirname, '..', 'clients', 'js'); kinobi.accept( - renderJavaScriptVisitor(path.join(jsClient, "src", "generated"), { - prettier: require(path.join(jsClient, ".prettierrc.json")), + renderJavaScriptVisitor(path.join(jsClient, 'src', 'generated'), { + prettier: require(path.join(jsClient, '.prettierrc.json')), }) ); diff --git a/scripts/link-solana-version.mjs b/scripts/link-solana-version.mjs new file mode 100644 index 0000000..acc0a04 --- /dev/null +++ b/scripts/link-solana-version.mjs @@ -0,0 +1,56 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mjs'; + +const installedVersion = await getInstalledSolanaVersion(); +const expectedVersion = getSolanaVersion(); + +if (installedVersion === expectedVersion) { + echo( + chalk.green('[ SUCCESS ]'), + `The expected Solana version ${expectedVersion} is installed.` + ); + process.exit(0); +} + +const installPath = path.join( + os.homedir(), + '.local', + 'share', + 'solana', + 'install' +); +const releasePath = path.join( + installPath, + 'releases', + expectedVersion, + 'solana-release' +); +const activeReleasePath = path.join(installPath, 'active_release'); +const hasRelease = await fs.exists(releasePath); + +if (hasRelease) { + await $`rm -f "${activeReleasePath}"`; + await $`ln -s "${releasePath}" "${activeReleasePath}"`; + echo( + chalk.green('[ SUCCESS ]'), + `Successfully switched from Solana version ${installedVersion} to ${expectedVersion} to match the project's requirements.` + ); + process.exit(0); +} + +echo( + chalk.yellow('[ WARNING ]'), + `Cannot switch from Solana version ${installedVersion} to ${expectedVersion} because it is not installed.` +); + +const installRelease = await question('Should we install it now? [y/N] '); +if (installRelease === 'y') { + echo(`Installing Solana ${expectedVersion}...`); + await $`sh -c "$(curl -sSfL https://release.solana.com/v${expectedVersion}/install)"`; +} + +echo( + chalk.green('[ SUCCESS ]'), + `Successfully switched from Solana version ${installedVersion} to ${expectedVersion} to match the project's requirements.` +); diff --git a/scripts/start-validator.mjs b/scripts/start-validator.mjs index 72b02b0..1adbcab 100644 --- a/scripts/start-validator.mjs +++ b/scripts/start-validator.mjs @@ -4,11 +4,15 @@ import fs from 'node:fs'; import 'zx/globals'; import { getCargo, + getExternalAccountAddresses, getExternalProgramAddresses, getExternalProgramOutputDir, getProgramFolders, } from './utils.mjs'; +// Check Solana version. +await $`pnpm solana:check`; + // Options and arguments. const restart = argv['restart']; @@ -21,10 +25,18 @@ if (!restart && isValidatorRunning) { // Initial message. const verb = isValidatorRunning ? 'Restarting' : 'Starting'; + +// Get programs and accounts. const programs = [...getPrograms(), ...getExternalPrograms()]; const programPluralized = programs.length === 1 ? 'program' : 'programs'; +const accounts = [...getExternalAccounts()]; +const accountsPluralized = accounts.length === 1 ? 'account' : 'accounts'; + echo( - `${verb} local validator with ${programs.length} custom ${programPluralized}...` + `${verb} local validator with ${programs.length} custom ${programPluralized}` + + (accounts.length > 0 + ? ` and ${accounts.length} external ${accountsPluralized}...` + : `...`) ); // Kill the validator if it's already running. @@ -41,6 +53,11 @@ programs.forEach(({ programId, deployPath }) => { args.push(/* Load BPF program */ '--bpf-program', programId, deployPath); }); +// Load accounts. +accounts.forEach(({ account, deployPath }) => { + args.push(/* Load account */ '--account', account, deployPath); +}); + // Start the validator in detached mode. const cliLogs = path.join(os.tmpdir(), 'validator-cli.log'); fs.writeFileSync(cliLogs, '', () => {}); @@ -98,3 +115,11 @@ function getExternalPrograms() { deployPath: path.join(binaryDir, `${address}.so`), })); } + +function getExternalAccounts() { + const binaryDir = getExternalProgramOutputDir(); + return getExternalAccountAddresses().map((address) => ({ + account: address, + deployPath: path.join(binaryDir, `${address}.json`), + })); +} diff --git a/scripts/upgrade-template.mjs b/scripts/upgrade-template.mjs new file mode 100644 index 0000000..1905b60 --- /dev/null +++ b/scripts/upgrade-template.mjs @@ -0,0 +1,58 @@ +#!/usr/bin/env zx +import 'zx/globals'; +import { getCargo } from './utils.mjs'; + +// Arguments to pass to the `create-solana-program` command. +const rustClientCargo = getCargo(path.join('clients', 'rust')); +const jsClientPkg = require( + path.join(__dirname, '..', 'clients', 'js', 'package.json') +); +const templateArgs = [ + 'token-2022', + '--address', + 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', + '--org', + 'solana-program', + '--rust-client-crate-name', + rustClientCargo.package.name, + '--js-client-package-name', + jsClientPkg.name, + '--default', + '--force', +]; + +// File and folder patterns that should not be overwritten by the template upgrade. +const unchangedGlobs = [ + 'clients/**/src/**', + 'clients/**/src/*', + 'clients/js/test/*', + 'clients/rust/tests/*', + 'program/**/*', + 'program/*', + 'scripts/generate-clients.mjs', + 'scripts/generate-idls.mjs', + 'scripts/upgrade-template.mjs', + 'scripts/program/*', + 'Cargo.lock', + '**/pnpm-lock.yaml', + 'pnpm-lock.yaml', +]; + +// Prevent CLI arguments from being escaped. +$.quote = (command) => command; + +// Re-generate the repo from the parent directory. +cd('..'); +await $`pnpm create solana-program@latest ${templateArgs}`; + +// Go back inside the updated repo. +cd('token-2022'); + +// Restore files and folders that should not be overwritten. +await $`git add --all`; +for (const glob of unchangedGlobs) { + await $`git restore --worktree --staged "${glob}"`; +} + +// Re-install dependencies. +await $`pnpm install`; diff --git a/scripts/utils.mjs b/scripts/utils.mjs index d5c3fc4..274f217 100644 --- a/scripts/utils.mjs +++ b/scripts/utils.mjs @@ -13,24 +13,38 @@ export function getAllProgramIdls() { } export function getExternalProgramOutputDir() { - const config = - getCargo().workspace?.metadata?.solana?.['external-programs-output']; + const config = getCargoMetadata()?.solana?.['external-programs-output']; return path.join(workingDirectory, config ?? 'target/deploy'); } export function getExternalProgramAddresses() { const addresses = getProgramFolders().flatMap( - (folder) => - getCargo(folder).package?.metadata?.solana?.['program-dependencies'] ?? [] + (folder) => getCargoMetadata(folder)?.solana?.['program-dependencies'] ?? [] + ); + return Array.from(new Set(addresses)); +} + +export function getExternalAccountAddresses() { + const addresses = getProgramFolders().flatMap( + (folder) => getCargoMetadata(folder)?.solana?.['account-dependencies'] ?? [] ); return Array.from(new Set(addresses)); } let didWarnAboutMissingPrograms = false; export function getProgramFolders() { - const programs = process.env.PROGRAMS - ? process.env.PROGRAMS.split(/\s+/) - : getAllProgramFolders(); + let programs; + + if (process.env.PROGRAMS) { + try { + programs = JSON.parse(process.env.PROGRAMS); + } catch (error) { + programs = process.env.PROGRAMS.split(/\s+/); + } + } else { + programs = getAllProgramFolders(); + } + const filteredPrograms = programs.filter((program) => fs.existsSync(path.join(workingDirectory, program)) ); @@ -64,3 +78,53 @@ export function getCargo(folder) { ) ); } + +export function getCargoMetadata(folder) { + const cargo = getCargo(folder); + return folder ? cargo?.package?.metadata : cargo?.workspace?.metadata; +} + +export function getSolanaVersion() { + return getCargoMetadata()?.cli?.solana; +} + +export function getToolchain(operation) { + return getCargoMetadata()?.toolchains?.[operation]; +} + +export function getToolchainArgument(operation) { + const channel = getToolchain(operation); + return channel ? `+${channel}` : ''; +} + +export function cliArguments() { + return process.argv.slice(3); +} + +export function popArgument(args, arg) { + const index = args.indexOf(arg); + if (index >= 0) { + args.splice(index, 1); + } + return index >= 0; +} + +export function partitionArguments(args, delimiter) { + const index = args.indexOf(delimiter); + return index >= 0 + ? [args.slice(0, index), args.slice(index + 1)] + : [args, []]; +} + +export async function getInstalledSolanaVersion() { + try { + const { stdout } = await $`solana --version`.quiet(); + return stdout.match(/(\d+\.\d+\.\d+)/)?.[1]; + } catch (error) { + echo( + chalk.red('[ ERROR ]'), + `No Solana installation found. Please install Solana ${getSolanaVersion()} before proceeding.` + ); + process.exit(1); + } +}