run (
    query,
    parameters,
    {
      bookmarks,
      txConfig,
      database,
      mode,
      impersonatedUser,
      notificationFilter,
      beforeKeys,
      afterKeys,
      beforeError,
      afterError,
      beforeComplete,
      afterComplete,
      flush = true,
      highRecordWatermark = Number.MAX_VALUE,
      lowRecordWatermark = Number.MAX_VALUE
    } = {}
  ) {
    const observer = new ResultStreamObserver({
      server: this._server,
      beforeKeys,
      afterKeys,
      beforeError,
      afterError,
      beforeComplete,
      afterComplete,
      highRecordWatermark,
      lowRecordWatermark
    })

    // bookmarks and mode are ignored in this version of the protocol
    assertTxConfigIsEmpty(txConfig, this._onProtocolError, observer)
    // passing in a database name on this protocol version throws an error
    assertDatabaseIsEmpty(database, this._onProtocolError, observer)
    // passing impersonated user on this protocol version throws an error
    assertImpersonatedUserIsEmpty(impersonatedUser, this._onProtocolError, observer)
    // passing notification filter on this protocol version throws an error
    assertNotificationFilterIsEmpty(notificationFilter, this._onProtocolError, observer)

    this.write(RequestMessage.run(query, parameters), observer, false)
    this.write(RequestMessage.pullAll(), observer, flush)

    return observer
  }
Send a Cypher query through the underlying connection.
@param {string} query the cypher query.
@param {Object} parameters the query parameters.
@param {Object} param
@param {Bookmarks} param.bookmarks the bookmarks.
@param {TxConfig} param.txConfig the transaction configuration.
@param {string} param.database the target database name.
@param {string} param.impersonatedUser the impersonated user
@param {NotificationFilter} param.notificationFilter the notification filter.
@param {string} param.mode the access mode.
@param {function(keys: string[])} param.beforeKeys the callback to invoke before handling the keys.
@param {function(keys: string[])} param.afterKeys the callback to invoke after handling the keys.
@param {function(err: Error)} param.beforeError the callback to invoke before handling the error.
@param {function(err: Error)} param.afterError the callback to invoke after handling the error.
@param {function()} param.beforeComplete the callback to invoke before handling the completion.
@param {function()} param.afterComplete the callback to invoke after handling the completion.
@param {boolean} param.flush whether to flush the buffered messages.
@returns {StreamObserver} the stream observer that monitors the corresponding server response.