瀏覽代碼

Update from latest `create-solana-program` (#11)

Loris Leiva 1 年之前
父節點
當前提交
b9dd270882

+ 103 - 0
.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 }}

+ 96 - 0
.github/workflows/main.yml

@@ -0,0 +1,96 @@
+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:
+    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:
+    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

+ 95 - 0
.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 }}

+ 122 - 0
.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 }}

+ 9 - 0
.prettierrc

@@ -0,0 +1,9 @@
+{
+  "semi": true,
+  "singleQuote": true,
+  "trailingComma": "es5",
+  "useTabs": false,
+  "tabWidth": 2,
+  "arrowParens": "always",
+  "printWidth": 80
+}

+ 1 - 1
Cargo.lock

@@ -4412,7 +4412,7 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "solana-system-client"
 name = "solana-system-client"
-version = "0.1.0"
+version = "0.0.0"
 dependencies = [
 dependencies = [
  "assert_matches",
  "assert_matches",
  "borsh 0.10.3",
  "borsh 0.10.3",

+ 9 - 0
Cargo.toml

@@ -1,3 +1,12 @@
 [workspace]
 [workspace]
 resolver = "2"
 resolver = "2"
 members = ["clients/rust"]
 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"

文件差異過大導致無法顯示
+ 1 - 0
README.md


+ 1 - 2
clients/js/README.md

@@ -17,8 +17,7 @@ This will start a new local validator, if one is not already running, and run th
 Alternatively, you can go into the client directory and run the tests directly.
 Alternatively, you can go into the client directory and run the tests directly.
 
 
 ```sh
 ```sh
-# Build your programs and start the validator.
-pnpm programs:build
+# Start the validator.
 pnpm validator:restart
 pnpm validator:restart
 
 
 # Go into the client directory and run the tests.
 # Go into the client directory and run the tests.

+ 7 - 4
clients/js/package.json

@@ -39,21 +39,24 @@
   "devDependencies": {
   "devDependencies": {
     "@ava/typescript": "^4.1.0",
     "@ava/typescript": "^4.1.0",
     "@solana/eslint-config-solana": "^3.0.3",
     "@solana/eslint-config-solana": "^3.0.3",
-    "@solana/web3.js": "tp4",
-    "@solana/webcrypto-ed25519-polyfill": "tp4",
-    "@types/node": "^20.14.11",
+    "@solana/web3.js": "2.0.0-preview.4",
+    "@solana/webcrypto-ed25519-polyfill": "2.0.0-preview.4",
+    "@types/node": "^20",
     "@typescript-eslint/eslint-plugin": "^7.16.1",
     "@typescript-eslint/eslint-plugin": "^7.16.1",
     "@typescript-eslint/parser": "^7.16.1",
     "@typescript-eslint/parser": "^7.16.1",
     "ava": "^6.1.3",
     "ava": "^6.1.3",
     "eslint": "^8.57.0",
     "eslint": "^8.57.0",
     "prettier": "^3.3.3",
     "prettier": "^3.3.3",
     "rimraf": "^5.0.5",
     "rimraf": "^5.0.5",
-    "tsup": "^8.0.2",
+    "tsup": "^8.1.2",
     "typedoc": "^0.25.12",
     "typedoc": "^0.25.12",
     "typedoc-plugin-missing-exports": "^2.2.0",
     "typedoc-plugin-missing-exports": "^2.2.0",
     "typescript": "^5.5.3"
     "typescript": "^5.5.3"
   },
   },
   "ava": {
   "ava": {
+    "nodeArguments": [
+      "--no-warnings"
+    ],
     "require": [
     "require": [
       "@solana/webcrypto-ed25519-polyfill"
       "@solana/webcrypto-ed25519-polyfill"
     ],
     ],

+ 255 - 219
clients/js/pnpm-lock.yaml

@@ -15,13 +15,13 @@ importers:
         specifier: ^3.0.3
         specifier: ^3.0.3
         version: 3.0.3(@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-react-hooks@4.6.0(eslint@8.57.0))(eslint-plugin-simple-import-sort@10.0.0(eslint@8.57.0))(eslint-plugin-sort-keys-fix@1.1.2)(eslint-plugin-typescript-sort-keys@3.2.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
         version: 3.0.3(@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-react-hooks@4.6.0(eslint@8.57.0))(eslint-plugin-simple-import-sort@10.0.0(eslint@8.57.0))(eslint-plugin-sort-keys-fix@1.1.2)(eslint-plugin-typescript-sort-keys@3.2.0(@typescript-eslint/parser@7.16.1(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
       '@solana/web3.js':
       '@solana/web3.js':
-        specifier: tp4
+        specifier: 2.0.0-preview.4
         version: 2.0.0-preview.4(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3)(ws@8.16.0)
         version: 2.0.0-preview.4(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3)(ws@8.16.0)
       '@solana/webcrypto-ed25519-polyfill':
       '@solana/webcrypto-ed25519-polyfill':
-        specifier: tp4
+        specifier: 2.0.0-preview.4
         version: 2.0.0-preview.4(typescript@5.5.3)
         version: 2.0.0-preview.4(typescript@5.5.3)
       '@types/node':
       '@types/node':
-        specifier: ^20.14.11
+        specifier: ^20
         version: 20.14.11
         version: 20.14.11
       '@typescript-eslint/eslint-plugin':
       '@typescript-eslint/eslint-plugin':
         specifier: ^7.16.1
         specifier: ^7.16.1
@@ -42,8 +42,8 @@ importers:
         specifier: ^5.0.5
         specifier: ^5.0.5
         version: 5.0.5
         version: 5.0.5
       tsup:
       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)
       typedoc:
       typedoc:
         specifier: ^0.25.12
         specifier: ^0.25.12
         version: 0.25.13(typescript@5.5.3)
         version: 0.25.13(typescript@5.5.3)
@@ -64,141 +64,147 @@ packages:
     resolution: {integrity: sha512-1iWZQ/nr9iflhLK9VN8H+1oDZqe93qxNnyYUz+jTzkYPAHc5fdZXBrqmNIgIfFhWYXK5OaQ5YtC7OmLeTNhVEg==}
     resolution: {integrity: sha512-1iWZQ/nr9iflhLK9VN8H+1oDZqe93qxNnyYUz+jTzkYPAHc5fdZXBrqmNIgIfFhWYXK5OaQ5YtC7OmLeTNhVEg==}
     engines: {node: ^14.19 || ^16.15 || ^18 || ^20}
     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]
     cpu: [ppc64]
     os: [aix]
     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]
     cpu: [arm64]
     os: [android]
     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]
     cpu: [arm]
     os: [android]
     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]
     cpu: [x64]
     os: [android]
     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]
     cpu: [arm64]
     os: [darwin]
     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]
     cpu: [x64]
     os: [darwin]
     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]
     cpu: [arm64]
     os: [freebsd]
     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]
     cpu: [x64]
     os: [freebsd]
     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]
     cpu: [arm64]
     os: [linux]
     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]
     cpu: [arm]
     os: [linux]
     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]
     cpu: [ia32]
     os: [linux]
     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]
     cpu: [loong64]
     os: [linux]
     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]
     cpu: [mips64el]
     os: [linux]
     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]
     cpu: [ppc64]
     os: [linux]
     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]
     cpu: [riscv64]
     os: [linux]
     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]
     cpu: [s390x]
     os: [linux]
     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]
     cpu: [x64]
     os: [linux]
     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]
     cpu: [x64]
     os: [netbsd]
     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]
     cpu: [x64]
     os: [openbsd]
     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]
     cpu: [x64]
     os: [sunos]
     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]
     cpu: [arm64]
     os: [win32]
     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]
     cpu: [ia32]
     os: [win32]
     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]
     cpu: [x64]
     os: [win32]
     os: [win32]
 
 
@@ -280,83 +286,83 @@ packages:
     resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
     resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
     engines: {node: '>= 8.0.0'}
     engines: {node: '>= 8.0.0'}
 
 
-  '@rollup/rollup-android-arm-eabi@4.16.3':
-    resolution: {integrity: sha512-1ACInKIT0pXmTYuPoJAL8sOT0lV3PEACFSVxnD03hGIojJ1CmbzZmLJyk2xew+yxqTlmx7xydkiJcBzdp0V+AQ==}
+  '@rollup/rollup-android-arm-eabi@4.19.1':
+    resolution: {integrity: sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==}
     cpu: [arm]
     cpu: [arm]
     os: [android]
     os: [android]
 
 
-  '@rollup/rollup-android-arm64@4.16.3':
-    resolution: {integrity: sha512-vGl+Bny8cawCM7ExugzqEB8ke3t7Pm9/mo+ciA9kJh6pMuNyM+31qhewMwHwseDZ/LtdW0SCocW1CsMxcq1Lsg==}
+  '@rollup/rollup-android-arm64@4.19.1':
+    resolution: {integrity: sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==}
     cpu: [arm64]
     cpu: [arm64]
     os: [android]
     os: [android]
 
 
-  '@rollup/rollup-darwin-arm64@4.16.3':
-    resolution: {integrity: sha512-Lj8J9WzQRvfWO4GfI+bBkIThUFV1PtI+es/YH/3cwUQ+edXu8Mre0JRJfRrAeRjPiHDPFFZaX51zfgHHEhgRAg==}
+  '@rollup/rollup-darwin-arm64@4.19.1':
+    resolution: {integrity: sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==}
     cpu: [arm64]
     cpu: [arm64]
     os: [darwin]
     os: [darwin]
 
 
-  '@rollup/rollup-darwin-x64@4.16.3':
-    resolution: {integrity: sha512-NPPOXMTIWJk50lgZmRReEYJFvLG5rgMDzaVauWNB2MgFQYm9HuNXQdVVg3iEZ3A5StIzxhMlPjVyS5fsv4PJmg==}
+  '@rollup/rollup-darwin-x64@4.19.1':
+    resolution: {integrity: sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==}
     cpu: [x64]
     cpu: [x64]
     os: [darwin]
     os: [darwin]
 
 
-  '@rollup/rollup-linux-arm-gnueabihf@4.16.3':
-    resolution: {integrity: sha512-ij4tv1XtWcDScaTgoMnvDEYZ2Wjl2ZhDFEyftjBKu6sNNLHIkKuXBol/bVSh+md5zSJ6em9hUXyPO3cVPCsl4Q==}
+  '@rollup/rollup-linux-arm-gnueabihf@4.19.1':
+    resolution: {integrity: sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==}
     cpu: [arm]
     cpu: [arm]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-arm-musleabihf@4.16.3':
-    resolution: {integrity: sha512-MTMAl30dzcfYB+smHe1sJuS2P1/hB8pqylkCe0/8/Lo8CADjy/eM8x43nBoR5eqcYgpOtCh7IgHpvqSMAE38xw==}
+  '@rollup/rollup-linux-arm-musleabihf@4.19.1':
+    resolution: {integrity: sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==}
     cpu: [arm]
     cpu: [arm]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-arm64-gnu@4.16.3':
-    resolution: {integrity: sha512-vY3fAg6JLDoNh781HHHMPvt8K6RWG3OmEj3xI9BOFSQTD5PNaGKvCB815MyGlDnFYUw7lH+WvvQqoBwLtRDR1A==}
+  '@rollup/rollup-linux-arm64-gnu@4.19.1':
+    resolution: {integrity: sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-arm64-musl@4.16.3':
-    resolution: {integrity: sha512-61SpQGBSb8QkfV/hUYWezlEig4ro55t8NcE5wWmy1bqRsRVHCEDkF534d+Lln/YeLUoSWtJHvvG3bx9lH/S6uA==}
+  '@rollup/rollup-linux-arm64-musl@4.19.1':
+    resolution: {integrity: sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==}
     cpu: [arm64]
     cpu: [arm64]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-powerpc64le-gnu@4.16.3':
-    resolution: {integrity: sha512-4XGexJthsNhEEgv/zK4/NnAOjYKoeCsIoT+GkqTY2u3rse0lbJ8ft1bpDCdlkvifsLDL2uwe4fn8PLR4IMTKQQ==}
+  '@rollup/rollup-linux-powerpc64le-gnu@4.19.1':
+    resolution: {integrity: sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==}
     cpu: [ppc64]
     cpu: [ppc64]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-riscv64-gnu@4.16.3':
-    resolution: {integrity: sha512-/pArXjqnEdhbQ1qe4CTTlJ6/GjWGdWNRucKAp4fqKnKf7QC0BES3QEV34ACumHHQ4uEGt4GctF2ISCMRhkli0A==}
+  '@rollup/rollup-linux-riscv64-gnu@4.19.1':
+    resolution: {integrity: sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==}
     cpu: [riscv64]
     cpu: [riscv64]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-s390x-gnu@4.16.3':
-    resolution: {integrity: sha512-vu4f3Y8iwjtRfSZdmtP8nC1jmRx1IrRVo2cLQlQfpFZ0e2AE9YbPgfIzpuK+i3C4zFETaLLNGezbBns2NuS/uA==}
+  '@rollup/rollup-linux-s390x-gnu@4.19.1':
+    resolution: {integrity: sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==}
     cpu: [s390x]
     cpu: [s390x]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-x64-gnu@4.16.3':
-    resolution: {integrity: sha512-n4HEgIJulNSmAKT3SYF/1wuzf9od14woSBseNkzur7a+KJIbh2Jb+J9KIsdGt3jJnsLW0BT1Sj6MiwL4Zzku6Q==}
+  '@rollup/rollup-linux-x64-gnu@4.19.1':
+    resolution: {integrity: sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-linux-x64-musl@4.16.3':
-    resolution: {integrity: sha512-guO/4N1884ig2AzTKPc6qA7OTnFMUEg/X2wiesywRO1eRD7FzHiaiTQQOLFmnUXWj2pgQXIT1g5g3e2RpezXcQ==}
+  '@rollup/rollup-linux-x64-musl@4.19.1':
+    resolution: {integrity: sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==}
     cpu: [x64]
     cpu: [x64]
     os: [linux]
     os: [linux]
 
 
-  '@rollup/rollup-win32-arm64-msvc@4.16.3':
-    resolution: {integrity: sha512-+rxD3memdkhGz0NhNqbYHXBoA33MoHBK4uubZjF1IeQv1Psi6tqgsCcC6vwQjxBM1qoCqOQQBy0cgNbbZKnGUg==}
+  '@rollup/rollup-win32-arm64-msvc@4.19.1':
+    resolution: {integrity: sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==}
     cpu: [arm64]
     cpu: [arm64]
     os: [win32]
     os: [win32]
 
 
-  '@rollup/rollup-win32-ia32-msvc@4.16.3':
-    resolution: {integrity: sha512-0NxVbLhBXmwANWWbgZY/RdSkeuHEgF+u8Dc0qBowUVBYsR2y2vwVGjKgUcj1wtu3jpjs057io5g9HAPr3Icqjg==}
+  '@rollup/rollup-win32-ia32-msvc@4.19.1':
+    resolution: {integrity: sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==}
     cpu: [ia32]
     cpu: [ia32]
     os: [win32]
     os: [win32]
 
 
-  '@rollup/rollup-win32-x64-msvc@4.16.3':
-    resolution: {integrity: sha512-hutnZavtOx/G4uVdgoZz5279By9NVbgmxOmGGgnzUjZYuwp2+NzGq6KXQmHXBWz7W/vottXn38QmKYAdQLa/vQ==}
+  '@rollup/rollup-win32-x64-msvc@4.19.1':
+    resolution: {integrity: sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==}
     cpu: [x64]
     cpu: [x64]
     os: [win32]
     os: [win32]
 
 
@@ -787,11 +793,11 @@ packages:
     resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
     resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
     engines: {node: '>=8'}
     engines: {node: '>=8'}
 
 
-  bundle-require@4.0.3:
-    resolution: {integrity: sha512-2iscZ3fcthP2vka4Y7j277YJevwmsby/FpFDwjgw34Nl7dtCpt7zz/4TexmHMzY6KZEih7En9ImlbbgUNNQGtA==}
+  bundle-require@5.0.0:
+    resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     peerDependencies:
     peerDependencies:
-      esbuild: '>=0.17'
+      esbuild: '>=0.18'
 
 
   cac@6.7.14:
   cac@6.7.14:
     resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
     resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
@@ -876,6 +882,10 @@ packages:
     resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==}
     resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==}
     engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'}
     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:
   console-control-strings@1.1.0:
     resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
     resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
 
 
@@ -904,6 +914,15 @@ packages:
       supports-color:
       supports-color:
         optional: true
         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:
   deep-is@0.1.4:
     resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
     resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
 
 
@@ -938,9 +957,9 @@ packages:
   emoji-regex@9.2.2:
   emoji-regex@9.2.2:
     resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
     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
     hasBin: true
 
 
   escalade@3.1.2:
   escalade@3.1.2:
@@ -1555,6 +1574,9 @@ packages:
     resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==}
     resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==}
     engines: {node: '>=12'}
     engines: {node: '>=12'}
 
 
+  picocolors@1.0.1:
+    resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
+
   picomatch@2.3.1:
   picomatch@2.3.1:
     resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
     resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
     engines: {node: '>=8.6'}
     engines: {node: '>=8.6'}
@@ -1571,16 +1593,22 @@ packages:
     resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==}
     resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     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:
     peerDependencies:
+      jiti: '>=1.21.0'
       postcss: '>=8.0.9'
       postcss: '>=8.0.9'
-      ts-node: '>=9.0.0'
+      tsx: ^4.8.1
+      yaml: ^2.4.2
     peerDependenciesMeta:
     peerDependenciesMeta:
+      jiti:
+        optional: true
       postcss:
       postcss:
         optional: true
         optional: true
-      ts-node:
+      tsx:
+        optional: true
+      yaml:
         optional: true
         optional: true
 
 
   prelude-ls@1.2.1:
   prelude-ls@1.2.1:
@@ -1644,8 +1672,8 @@ packages:
     engines: {node: '>=14'}
     engines: {node: '>=14'}
     hasBin: true
     hasBin: true
 
 
-  rollup@4.16.3:
-    resolution: {integrity: sha512-Ygm4fFO4usWcAG3Ud36Lmif5nudoi0X6QPLC+kRgrRjulAbmFkaTawP7fTIkRDnCNSf/4IAQzXM1T8e691kRtw==}
+  rollup@4.19.1:
+    resolution: {integrity: sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==}
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
     hasBin: true
     hasBin: true
 
 
@@ -1808,8 +1836,8 @@ packages:
   tslib@1.14.1:
   tslib@1.14.1:
     resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
     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'}
     engines: {node: '>=18'}
     hasBin: true
     hasBin: true
     peerDependencies:
     peerDependencies:
@@ -1942,11 +1970,6 @@ packages:
   yallist@4.0.0:
   yallist@4.0.0:
     resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
     resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
 
 
-  yaml@2.4.1:
-    resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==}
-    engines: {node: '>= 14'}
-    hasBin: true
-
   yargs-parser@21.1.1:
   yargs-parser@21.1.1:
     resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
     resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
     engines: {node: '>=12'}
     engines: {node: '>=12'}
@@ -1968,73 +1991,76 @@ snapshots:
       escape-string-regexp: 5.0.0
       escape-string-regexp: 5.0.0
       execa: 7.2.0
       execa: 7.2.0
 
 
-  '@esbuild/aix-ppc64@0.19.12':
+  '@esbuild/aix-ppc64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/android-arm64@0.19.12':
+  '@esbuild/android-arm64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/android-arm@0.19.12':
+  '@esbuild/android-arm@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/android-x64@0.19.12':
+  '@esbuild/android-x64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/darwin-arm64@0.19.12':
+  '@esbuild/darwin-arm64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/darwin-x64@0.19.12':
+  '@esbuild/darwin-x64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/freebsd-arm64@0.19.12':
+  '@esbuild/freebsd-arm64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/freebsd-x64@0.19.12':
+  '@esbuild/freebsd-x64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-arm64@0.19.12':
+  '@esbuild/linux-arm64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-arm@0.19.12':
+  '@esbuild/linux-arm@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-ia32@0.19.12':
+  '@esbuild/linux-ia32@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-loong64@0.19.12':
+  '@esbuild/linux-loong64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-mips64el@0.19.12':
+  '@esbuild/linux-mips64el@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-ppc64@0.19.12':
+  '@esbuild/linux-ppc64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-riscv64@0.19.12':
+  '@esbuild/linux-riscv64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-s390x@0.19.12':
+  '@esbuild/linux-s390x@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/linux-x64@0.19.12':
+  '@esbuild/linux-x64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/netbsd-x64@0.19.12':
+  '@esbuild/netbsd-x64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/openbsd-x64@0.19.12':
+  '@esbuild/openbsd-arm64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/sunos-x64@0.19.12':
+  '@esbuild/openbsd-x64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/win32-arm64@0.19.12':
+  '@esbuild/sunos-x64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/win32-ia32@0.19.12':
+  '@esbuild/win32-arm64@0.23.0':
     optional: true
     optional: true
 
 
-  '@esbuild/win32-x64@0.19.12':
+  '@esbuild/win32-ia32@0.23.0':
+    optional: true
+
+  '@esbuild/win32-x64@0.23.0':
     optional: true
     optional: true
 
 
   '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
   '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
@@ -2135,52 +2161,52 @@ snapshots:
       estree-walker: 2.0.2
       estree-walker: 2.0.2
       picomatch: 2.3.1
       picomatch: 2.3.1
 
 
-  '@rollup/rollup-android-arm-eabi@4.16.3':
+  '@rollup/rollup-android-arm-eabi@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-android-arm64@4.16.3':
+  '@rollup/rollup-android-arm64@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-darwin-arm64@4.16.3':
+  '@rollup/rollup-darwin-arm64@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-darwin-x64@4.16.3':
+  '@rollup/rollup-darwin-x64@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-arm-gnueabihf@4.16.3':
+  '@rollup/rollup-linux-arm-gnueabihf@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-arm-musleabihf@4.16.3':
+  '@rollup/rollup-linux-arm-musleabihf@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-arm64-gnu@4.16.3':
+  '@rollup/rollup-linux-arm64-gnu@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-arm64-musl@4.16.3':
+  '@rollup/rollup-linux-arm64-musl@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-powerpc64le-gnu@4.16.3':
+  '@rollup/rollup-linux-powerpc64le-gnu@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-riscv64-gnu@4.16.3':
+  '@rollup/rollup-linux-riscv64-gnu@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-s390x-gnu@4.16.3':
+  '@rollup/rollup-linux-s390x-gnu@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-x64-gnu@4.16.3':
+  '@rollup/rollup-linux-x64-gnu@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-linux-x64-musl@4.16.3':
+  '@rollup/rollup-linux-x64-musl@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-win32-arm64-msvc@4.16.3':
+  '@rollup/rollup-win32-arm64-msvc@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-win32-ia32-msvc@4.16.3':
+  '@rollup/rollup-win32-ia32-msvc@4.19.1':
     optional: true
     optional: true
 
 
-  '@rollup/rollup-win32-x64-msvc@4.16.3':
+  '@rollup/rollup-win32-x64-msvc@4.19.1':
     optional: true
     optional: true
 
 
   '@sindresorhus/merge-streams@2.3.0': {}
   '@sindresorhus/merge-streams@2.3.0': {}
@@ -2828,9 +2854,9 @@ snapshots:
     dependencies:
     dependencies:
       fill-range: 7.0.1
       fill-range: 7.0.1
 
 
-  bundle-require@4.0.3(esbuild@0.19.12):
+  bundle-require@5.0.0(esbuild@0.23.0):
     dependencies:
     dependencies:
-      esbuild: 0.19.12
+      esbuild: 0.23.0
       load-tsconfig: 0.2.5
       load-tsconfig: 0.2.5
 
 
   cac@6.7.14: {}
   cac@6.7.14: {}
@@ -2912,6 +2938,8 @@ snapshots:
       semver: 7.6.0
       semver: 7.6.0
       well-known-symbols: 2.0.0
       well-known-symbols: 2.0.0
 
 
+  consola@3.2.3: {}
+
   console-control-strings@1.1.0: {}
   console-control-strings@1.1.0: {}
 
 
   convert-to-spaces@2.0.1: {}
   convert-to-spaces@2.0.1: {}
@@ -2934,6 +2962,10 @@ snapshots:
     dependencies:
     dependencies:
       ms: 2.1.2
       ms: 2.1.2
 
 
+  debug@4.3.6:
+    dependencies:
+      ms: 2.1.2
+
   deep-is@0.1.4: {}
   deep-is@0.1.4: {}
 
 
   delegates@1.0.0: {}
   delegates@1.0.0: {}
@@ -2958,31 +2990,32 @@ snapshots:
 
 
   emoji-regex@9.2.2: {}
   emoji-regex@9.2.2: {}
 
 
-  esbuild@0.19.12:
+  esbuild@0.23.0:
     optionalDependencies:
     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: {}
   escalade@3.1.2: {}
 
 
@@ -3564,6 +3597,8 @@ snapshots:
 
 
   path-type@5.0.0: {}
   path-type@5.0.0: {}
 
 
+  picocolors@1.0.1: {}
+
   picomatch@2.3.1: {}
   picomatch@2.3.1: {}
 
 
   picomatch@3.0.1: {}
   picomatch@3.0.1: {}
@@ -3574,10 +3609,9 @@ snapshots:
     dependencies:
     dependencies:
       irregular-plurals: 3.5.0
       irregular-plurals: 3.5.0
 
 
-  postcss-load-config@4.0.2:
+  postcss-load-config@6.0.1:
     dependencies:
     dependencies:
       lilconfig: 3.1.1
       lilconfig: 3.1.1
-      yaml: 2.4.1
 
 
   prelude-ls@1.2.1: {}
   prelude-ls@1.2.1: {}
 
 
@@ -3623,26 +3657,26 @@ snapshots:
     dependencies:
     dependencies:
       glob: 10.3.12
       glob: 10.3.12
 
 
-  rollup@4.16.3:
+  rollup@4.19.1:
     dependencies:
     dependencies:
       '@types/estree': 1.0.5
       '@types/estree': 1.0.5
     optionalDependencies:
     optionalDependencies:
-      '@rollup/rollup-android-arm-eabi': 4.16.3
-      '@rollup/rollup-android-arm64': 4.16.3
-      '@rollup/rollup-darwin-arm64': 4.16.3
-      '@rollup/rollup-darwin-x64': 4.16.3
-      '@rollup/rollup-linux-arm-gnueabihf': 4.16.3
-      '@rollup/rollup-linux-arm-musleabihf': 4.16.3
-      '@rollup/rollup-linux-arm64-gnu': 4.16.3
-      '@rollup/rollup-linux-arm64-musl': 4.16.3
-      '@rollup/rollup-linux-powerpc64le-gnu': 4.16.3
-      '@rollup/rollup-linux-riscv64-gnu': 4.16.3
-      '@rollup/rollup-linux-s390x-gnu': 4.16.3
-      '@rollup/rollup-linux-x64-gnu': 4.16.3
-      '@rollup/rollup-linux-x64-musl': 4.16.3
-      '@rollup/rollup-win32-arm64-msvc': 4.16.3
-      '@rollup/rollup-win32-ia32-msvc': 4.16.3
-      '@rollup/rollup-win32-x64-msvc': 4.16.3
+      '@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
       fsevents: 2.3.3
 
 
   run-parallel@1.2.0:
   run-parallel@1.2.0:
@@ -3799,27 +3833,31 @@ snapshots:
 
 
   tslib@1.14.1: {}
   tslib@1.14.1: {}
 
 
-  tsup@8.0.2(typescript@5.5.3):
+  tsup@8.2.3(typescript@5.5.3):
     dependencies:
     dependencies:
-      bundle-require: 4.0.3(esbuild@0.19.12)
+      bundle-require: 5.0.0(esbuild@0.23.0)
       cac: 6.7.14
       cac: 6.7.14
       chokidar: 3.6.0
       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
       execa: 5.1.1
       globby: 11.1.0
       globby: 11.1.0
       joycon: 3.1.1
       joycon: 3.1.1
-      postcss-load-config: 4.0.2
+      picocolors: 1.0.1
+      postcss-load-config: 6.0.1
       resolve-from: 5.0.0
       resolve-from: 5.0.0
-      rollup: 4.16.3
+      rollup: 4.19.1
       source-map: 0.8.0-beta.0
       source-map: 0.8.0-beta.0
       sucrase: 3.35.0
       sucrase: 3.35.0
       tree-kill: 1.2.2
       tree-kill: 1.2.2
     optionalDependencies:
     optionalDependencies:
       typescript: 5.5.3
       typescript: 5.5.3
     transitivePeerDependencies:
     transitivePeerDependencies:
+      - jiti
       - supports-color
       - supports-color
-      - ts-node
+      - tsx
+      - yaml
 
 
   tsutils@3.21.0(typescript@5.5.3):
   tsutils@3.21.0(typescript@5.5.3):
     dependencies:
     dependencies:
@@ -3914,8 +3952,6 @@ snapshots:
 
 
   yallist@4.0.0: {}
   yallist@4.0.0: {}
 
 
-  yaml@2.4.1: {}
-
   yargs-parser@21.1.1: {}
   yargs-parser@21.1.1: {}
 
 
   yargs@17.7.2:
   yargs@17.7.2:

+ 24 - 0
clients/js/src/generated/errors/system.ts

@@ -6,6 +6,14 @@
  * @see https://github.com/kinobi-so/kinobi
  * @see https://github.com/kinobi-so/kinobi
  */
  */
 
 
+import {
+  isProgramError,
+  type Address,
+  type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM,
+  type SolanaError,
+} from '@solana/web3.js';
+import { SYSTEM_PROGRAM_ADDRESS } from '../programs';
+
 /** AccountAlreadyInUse: an account with the same address already exists */
 /** AccountAlreadyInUse: an account with the same address already exists */
 export const SYSTEM_ERROR__ACCOUNT_ALREADY_IN_USE = 0x0; // 0
 export const SYSTEM_ERROR__ACCOUNT_ALREADY_IN_USE = 0x0; // 0
 /** ResultWithNegativeLamports: account does not have enough SOL to perform the operation */
 /** ResultWithNegativeLamports: account does not have enough SOL to perform the operation */
@@ -58,3 +66,19 @@ export function getSystemErrorMessage(code: SystemError): string {
 
 
   return 'Error message not available in production bundles.';
   return 'Error message not available in production bundles.';
 }
 }
+
+export function isSystemError<TProgramErrorCode extends SystemError>(
+  error: unknown,
+  transactionMessage: {
+    instructions: Record<number, { programAddress: Address }>;
+  },
+  code?: TProgramErrorCode
+): error is SolanaError<typeof SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM> &
+  Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> {
+  return isProgramError<TProgramErrorCode>(
+    error,
+    transactionMessage,
+    SYSTEM_PROGRAM_ADDRESS,
+    code
+  );
+}

+ 8 - 4
clients/js/src/generated/programs/system.ts

@@ -6,7 +6,12 @@
  * @see https://github.com/kinobi-so/kinobi
  * @see https://github.com/kinobi-so/kinobi
  */
  */
 
 
-import { containsBytes, getU32Encoder, type Address } from '@solana/web3.js';
+import {
+  containsBytes,
+  getU32Encoder,
+  type Address,
+  type ReadonlyUint8Array,
+} from '@solana/web3.js';
 import {
 import {
   type ParsedAdvanceNonceAccountInstruction,
   type ParsedAdvanceNonceAccountInstruction,
   type ParsedAllocateInstruction,
   type ParsedAllocateInstruction,
@@ -47,10 +52,9 @@ export enum SystemInstruction {
 }
 }
 
 
 export function identifySystemInstruction(
 export function identifySystemInstruction(
-  instruction: { data: Uint8Array } | Uint8Array
+  instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array
 ): SystemInstruction {
 ): SystemInstruction {
-  const data =
-    instruction instanceof Uint8Array ? instruction : instruction.data;
+  const data = 'data' in instruction ? instruction.data : instruction;
   if (containsBytes(data, getU32Encoder().encode(0), 0)) {
   if (containsBytes(data, getU32Encoder().encode(0), 0)) {
     return SystemInstruction.CreateAccount;
     return SystemInstruction.CreateAccount;
   }
   }

+ 1 - 1
clients/js/tsconfig.declarations.json

@@ -3,7 +3,7 @@
     "declaration": true,
     "declaration": true,
     "declarationMap": true,
     "declarationMap": true,
     "emitDeclarationOnly": true,
     "emitDeclarationOnly": true,
-    "outDir": "./dist/types"
+    "outDir": "./dist/types",
   },
   },
   "extends": "./tsconfig.json",
   "extends": "./tsconfig.json",
   "include": ["src"]
   "include": ["src"]

+ 1 - 1
clients/js/tsup.config.ts

@@ -19,7 +19,7 @@ export default defineConfig(() => [
   {
   {
     ...SHARED_OPTIONS,
     ...SHARED_OPTIONS,
     bundle: false,
     bundle: false,
-    entry: ['./test/*.ts'],
+    entry: ['./test/**/*.ts'],
     format: 'cjs',
     format: 'cjs',
     outDir: './dist/test',
     outDir: './dist/test',
   },
   },

+ 3 - 1
clients/rust/Cargo.toml

@@ -1,6 +1,8 @@
 [package]
 [package]
 name = "solana-system-client"
 name = "solana-system-client"
-version = "0.1.0"
+version = "0.0.0"
+description = "A generated Rust library for the System program"
+repository = "https://github.com/solana-program/system"
 edition = "2021"
 edition = "2021"
 readme = "README.md"
 readme = "README.md"
 license-file = "../../LICENSE"
 license-file = "../../LICENSE"

+ 10 - 2
package.json

@@ -1,19 +1,27 @@
 {
 {
   "private": true,
   "private": true,
   "scripts": {
   "scripts": {
+    "solana:check": "zx ./scripts/check-solana-version.mjs",
+    "solana:link": "zx ./scripts/link-solana-version.mjs",
     "generate": "pnpm generate:clients",
     "generate": "pnpm generate:clients",
     "generate:clients": "zx ./scripts/generate-clients.mjs",
     "generate:clients": "zx ./scripts/generate-clients.mjs",
     "validator:start": "zx ./scripts/start-validator.mjs",
     "validator:start": "zx ./scripts/start-validator.mjs",
     "validator:restart": "pnpm validator:start --restart",
     "validator:restart": "pnpm validator:start --restart",
     "validator:stop": "zx ./scripts/stop-validator.mjs",
     "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:js:test": "zx ./scripts/client/test-js.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"
     "clients:rust:test": "zx ./scripts/client/test-rust.mjs"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@iarna/toml": "^2.2.5",
     "@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-so/renderers-rust": "^0.21.0",
+    "kinobi": "^0.21.0",
     "typescript": "^5.5.2",
     "typescript": "^5.5.2",
     "zx": "^7.2.3"
     "zx": "^7.2.3"
   },
   },

+ 5 - 5
pnpm-lock.yaml

@@ -12,8 +12,8 @@ importers:
         specifier: ^2.2.5
         specifier: ^2.2.5
         version: 2.2.5
         version: 2.2.5
       '@kinobi-so/renderers-js':
       '@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':
       '@kinobi-so/renderers-rust':
         specifier: ^0.21.0
         specifier: ^0.21.0
         version: 0.21.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3)
         version: 0.21.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3)
@@ -48,8 +48,8 @@ packages:
   '@kinobi-so/renderers-core@0.20.7':
   '@kinobi-so/renderers-core@0.20.7':
     resolution: {integrity: sha512-KJhU8+UMowO9dDkLhEodAkbRkgSxdfBWeY+DIgOCgXcakt0T140K7OREuaAo9fp12Owf+10SAEGx9AzTNySoHA==}
     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':
   '@kinobi-so/renderers-rust@0.21.0':
     resolution: {integrity: sha512-BLe1SW6XFBhjtZdCc7cuukMWrJTbhCafCCmXryLmjzF7jaiK9nyZZFinHxljSac4HCk2vDn22mHAwOjabaDQ2Q==}
     resolution: {integrity: sha512-BLe1SW6XFBhjtZdCc7cuukMWrJTbhCafCCmXryLmjzF7jaiK9nyZZFinHxljSac4HCk2vDn22mHAwOjabaDQ2Q==}
@@ -432,7 +432,7 @@ snapshots:
       '@kinobi-so/nodes': 0.21.0
       '@kinobi-so/nodes': 0.21.0
       '@kinobi-so/visitors-core': 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:
     dependencies:
       '@kinobi-so/errors': 0.21.0
       '@kinobi-so/errors': 0.21.0
       '@kinobi-so/nodes': 0.21.0
       '@kinobi-so/nodes': 0.21.0

+ 18 - 0
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.`
+  );
+}

+ 6 - 0
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`;

+ 8 - 0
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()}`;

+ 30 - 0
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}`;
+}

+ 8 - 0
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()}`;

+ 28 - 0
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}`;
+}

+ 35 - 0
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}"`;

+ 40 - 0
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}"`;

+ 3 - 3
scripts/client/test-js.mjs

@@ -1,12 +1,12 @@
 #!/usr/bin/env zx
 #!/usr/bin/env zx
 import 'zx/globals';
 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`;
 await $`pnpm validator:restart`;
 
 
 // Build the client and run the tests.
 // Build the client and run the tests.
 cd(path.join(workingDirectory, 'clients', 'js'));
 cd(path.join(workingDirectory, 'clients', 'js'));
 await $`pnpm install`;
 await $`pnpm install`;
 await $`pnpm build`;
 await $`pnpm build`;
-await $`pnpm test ${argv._}`;
+await $`pnpm test ${cliArguments()}`;

+ 11 - 6
scripts/client/test-rust.mjs

@@ -1,12 +1,17 @@
 #!/usr/bin/env zx
 #!/usr/bin/env zx
-import "zx/globals";
-import { workingDirectory } from "../utils.mjs";
+import 'zx/globals';
+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.
 // Run the tests.
-cd(path.join(workingDirectory, "clients", "rust"));
-const hasSolfmt = await which("solfmt", { nothrow: true });
+cd(path.join(workingDirectory, 'clients', 'rust'));
 if (hasSolfmt) {
 if (hasSolfmt) {
-  await $`cargo test-sbf ${argv._} 2>&1 | solfmt`;
+  await $`cargo test-sbf ${testArgs} 2>&1 | solfmt`;
 } else {
 } else {
-  await $`cargo test-sbf ${argv._}`;
+  await $`cargo test-sbf ${testArgs}`;
 }
 }

+ 56 - 0
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.`
+);

+ 26 - 1
scripts/start-validator.mjs

@@ -4,11 +4,15 @@ import fs from 'node:fs';
 import 'zx/globals';
 import 'zx/globals';
 import {
 import {
   getCargo,
   getCargo,
+  getExternalAccountAddresses,
   getExternalProgramAddresses,
   getExternalProgramAddresses,
   getExternalProgramOutputDir,
   getExternalProgramOutputDir,
   getProgramFolders,
   getProgramFolders,
 } from './utils.mjs';
 } from './utils.mjs';
 
 
+// Check Solana version.
+await $`pnpm solana:check`;
+
 // Options and arguments.
 // Options and arguments.
 const restart = argv['restart'];
 const restart = argv['restart'];
 
 
@@ -21,10 +25,18 @@ if (!restart && isValidatorRunning) {
 
 
 // Initial message.
 // Initial message.
 const verb = isValidatorRunning ? 'Restarting' : 'Starting';
 const verb = isValidatorRunning ? 'Restarting' : 'Starting';
+
+// Get programs and accounts.
 const programs = [...getPrograms(), ...getExternalPrograms()];
 const programs = [...getPrograms(), ...getExternalPrograms()];
 const programPluralized = programs.length === 1 ? 'program' : 'programs';
 const programPluralized = programs.length === 1 ? 'program' : 'programs';
+const accounts = [...getExternalAccounts()];
+const accountsPluralized = accounts.length === 1 ? 'account' : 'accounts';
+
 echo(
 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.
 // 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);
   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.
 // Start the validator in detached mode.
 const cliLogs = path.join(os.tmpdir(), 'validator-cli.log');
 const cliLogs = path.join(os.tmpdir(), 'validator-cli.log');
 fs.writeFileSync(cliLogs, '', () => {});
 fs.writeFileSync(cliLogs, '', () => {});
@@ -98,3 +115,11 @@ function getExternalPrograms() {
     deployPath: path.join(binaryDir, `${address}.so`),
     deployPath: path.join(binaryDir, `${address}.so`),
   }));
   }));
 }
 }
+
+function getExternalAccounts() {
+  const binaryDir = getExternalProgramOutputDir();
+  return getExternalAccountAddresses().map((address) => ({
+    account: address,
+    deployPath: path.join(binaryDir, `${address}.json`),
+  }));
+}

+ 25 - 0
scripts/upgrade-template.mjs

@@ -0,0 +1,25 @@
+#!/usr/bin/env zx
+import "zx/globals";
+
+$.quote = (command) => command;
+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/*",
+];
+
+cd("..");
+await $`pnpm create solana-program system --address 11111111111111111111111111111111 --default --force`;
+cd("system");
+await $`git add --all`;
+for (const glob of unchangedGlobs) {
+  await $`git restore --worktree --staged "${glob}"`;
+}
+await $`pnpm install`;

+ 71 - 7
scripts/utils.mjs

@@ -13,24 +13,38 @@ export function getAllProgramIdls() {
 }
 }
 
 
 export function getExternalProgramOutputDir() {
 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');
   return path.join(workingDirectory, config ?? 'target/deploy');
 }
 }
 
 
 export function getExternalProgramAddresses() {
 export function getExternalProgramAddresses() {
   const addresses = getProgramFolders().flatMap(
   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));
   return Array.from(new Set(addresses));
 }
 }
 
 
 let didWarnAboutMissingPrograms = false;
 let didWarnAboutMissingPrograms = false;
 export function getProgramFolders() {
 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) =>
   const filteredPrograms = programs.filter((program) =>
     fs.existsSync(path.join(workingDirectory, 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);
+  }
+}

部分文件因文件數量過多而無法顯示