How to sign EIP-712 format with web3js

I have example contract solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;


import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

contract SpaceStationV2 is  EIP712  {
       // The galaxy signer(EOA): used to verify EIP-712.
    address public galaxy_signer;

 /* ============ Constructor ============ */
    constructor(address _galaxy_signer) EIP712("Galaxy", "1.0.0") {
        galaxy_signer = _galaxy_signer;
    }
    
    
 /* ============ Internal Functions ============ */
    function _hash(
        uint256 _cid,
        address _starNFT,
        uint256 _dummyId,
        uint256 _powah,
        address _account
    ) public view returns (bytes32) {
        return
        _hashTypedDataV4(
            keccak256(
                abi.encode(
                    keccak256(
                        "NFT(uint256 cid,address starNFT,uint256 dummyId,uint256 powah,address account)"
                    ),
                    _cid,
                    _starNFT,
                    _dummyId,
                    _powah,
                    _account
                )
            )
        );
    }

        // todo: change to internal on PRD
    function _verify(bytes32 hash, bytes calldata signature)
    public
    view
    returns (bool)
    {
        return ECDSA.recover(hash, signature) == galaxy_signer;
    }
}

How to get sign(bytes) with web3js ?

I think there's no default web3.js implementation for signing EIP-712 messages.

I suggest looking at our 4.9.x tests for the MinimalForwarder. We made use of eth-sig-util instead