Skip to content

Releases: ClickHouse/clickhouse-js

1.6.0

12 Sep 18:34
fa85613
Compare
Choose a tag to compare

New features

Bug fixes

  • (Node.js) Fixed unhandled exceptions produced when calling ResultSet.json if the response data was not, in fact, a valid JSON. (#311)

1.5.0 (Common, Node.js)

22 Aug 13:41
43751b0
Compare
Choose a tag to compare

New features

  • (Node.js only) It is now possible to disable the automatic decompression of the response stream with the exec method. See ExecParams.decompress_response_stream for more details. (#298).

1.4.1 (Node.js, Web)

07 Aug 16:53
2988c50
Compare
Choose a tag to compare

Improvements

  • ClickHouseClient is now exported as a value from @clickhouse/client and @clickhouse/client-web packages, allowing for better integration in dependency injection frameworks that rely on IoC (e.g., Nest.js, tsyringe) (@mathieu-bour, #292).

Bug fixes

  • Fixed a potential socket hang-up issue that could happen under 100% CPU load (#294).

1.4.0 (Node.js only)

12 Jul 14:04
e78b6f0
Compare
Choose a tag to compare

New features

  • (Node.js only) The exec method now accepts an optional values parameter, which allows you to pass the request body as a Stream.Readable. This can be useful in the case of custom insert streaming with arbitrary ClickHouse data formats (which might not be explicitly supported and allowed by the client in the insert method yet). NB: in this case, you are expected to serialize the data in the stream in the required input format yourself. See #290 for more details.

Improvements

  • (Node.js only) The client package now exports a utility method drainStream

1.3.0 (Common, Node.js, Web)

08 Jul 12:41
30ce583
Compare
Choose a tag to compare

New features

  • It is now possible to get the entire response headers object from the query/insert/command/exec methods. With query, you can access the ResultSet.response_headers property; other methods (insert/command/exec) return it as parts of their response objects as well.
    For example:

    const rs = await client.query({
      query: 'SELECT * FROM system.numbers LIMIT 1',
      format: 'JSONEachRow',
    })
    console.log(rs.response_headers['content-type'])

    This will print: application/x-ndjson; charset=UTF-8. It can be used in a similar way with the other methods.

Improvements

  • Re-exported several constants from the @clickhouse/client-common package for convenience:

    • SupportedJSONFormats
    • SupportedRawFormats
    • StreamableFormats
    • StreamableJSONFormats
    • SingleDocumentJSONFormats
    • RecordsJSONFormats

1.2.0 (Node.js only)

19 Jun 13:40
e88d3eb
Compare
Choose a tag to compare

New features

  • (Experimental) Added an option to provide a custom HTTP Agent in the client configuration via the http_agent option (#283, related: #278). The following conditions apply if a custom HTTP Agent is provided:

    • The max_open_connections and tls options will have no effect and will be ignored by the client, as those are part of the underlying HTTP Agent configuration.
    • keep_alive.enabled will only regulate the default value of the Connection header (true -> Connection: keep-alive, false -> Connection: close).
    • While the idle socket management will still work, it is now possible to disable it completely by setting the keep_alive.idle_socket_ttl value to 0.
  • (Experimental) Added a new client configuration option: set_basic_auth_header, which controls whether the Authorization header should be set for every outgoing HTTP request (enabled by default). One of the possible scenarios when it is necessary to disable this header is when a custom HTTPS agent is used, and the server requires TLS with certificates. For example:

    const agent = new https.Agent({
      keepAlive: true,
      keepAliveMsecs: 2500,
      maxSockets: 10,
      maxFreeSockets: 10,
      ca: fs.readFileSync('./ca.crt'),
      cert: fs.readFileSync('./client.crt'),
      key: fs.readFileSync('./client.key'),
    })
    const client = createClient({
      url: 'https://myserver:8443',
      http_agent: agent,
      // With a custom HTTPS agent, the client won't use the default HTTPS connection implementation; the headers should be provided manually
      http_headers: {
        'X-ClickHouse-User': 'username',
        'X-ClickHouse-Key': 'password',
        'X-ClickHouse-SSL-Certificate-Auth': 'on',
      },
      // Important: authorization header conflicts with the TLS headers; disable it.
      set_basic_auth_header: false,
    })

NB: It is currently not possible to set the set_basic_auth_header option via the URL params.

See the doc entry regarding custom HTTP(s) Agent usage with code samples.

If you have feedback on these experimental features, please let us know by creating an issue in the repository or send a message in the Community Slack (#clickhouse-js channel).

1.1.0

06 Jun 19:29
9bdea17
Compare
Choose a tag to compare

New features

  • Added an option to override the credentials for a particular query/command/exec/insert request via the BaseQueryParams.auth setting; when set, the credentials will be taken from there instead of the username/password provided during the client instantiation (#278).
  • Added an option to override the session_id for a particular query/command/exec/insert request via the BaseQueryParams.session_id setting; when set, it will be used instead of the session id provided during the client instantiation (@holi0317, #271).

Bug fixes

  • Fixed the incorrect ResponseJSON<T>.totals TypeScript type. Now it correctly matches the shape of the data (T, default = unknown) instead of the former Record<string, number> definition (#274).

1.0.2

20 May 16:03
ad8611e
Compare
Choose a tag to compare

Bug fixes

  • The command method now drains the response stream properly, as the previous implementation could cause the Keep-Alive socket to close after each request.
  • (Node.js) Removed an unnecessary error log in the ResultSet.stream method if the request was aborted or the result set was closed (#263).

Improvements

  • (Node.js) ResultSet.stream logs an error via the Logger instance if the stream emits an error event instead of a simple console.error call.
  • Minor adjustments to the formatting of the DefaultLogger log messages.
  • Added missing rows_before_limit_at_least to the ResponseJSON type (@0237h, #267).

1.0.1

02 Apr 14:06
Compare
Choose a tag to compare

A hotfix for both Node.js and Web packages.
See the 1.0.0 entry that contains the entire 1.0.x changelog.

Bug fixes

  • Fixed the regression where the default HTTP/HTTPS port numbers (80/443) could not be used with the URL configuration (#258).

1.0.0

02 Apr 08:34
Compare
Choose a tag to compare

Formal stable release milestone with many improvements and some breaking changes.

Major new features overview:

  • Advanced TypeScript support for query + ResultSet
  • URL configuration

From now on, the client will follow the official semantic versioning guidelines.

Deprecated API

The following configuration parameters are marked as deprecated:

  • The host configuration parameter is deprecated; use url instead.
  • additional_headers configuration parameter is deprecated; use http_headers instead.

The client will log a warning if any of these parameters are used. However, it is still allowed to use host instead of url and additional_headers instead of http_headers for now; this deprecation is not supposed to break the existing code.

These parameters will be removed in the next major release (2.0.0).

See the "New features" section for more details.

Breaking changes in 1.0.0

  • compression.response is now disabled by default in the client configuration options, as it cannot be used with readonly=1 users, and it was not clear from the ClickHouse error message what exact client option was causing the failing query in this case. If you'd like to continue using response compression, you should explicitly enable it in the client configuration.
  • As the client now supports parsing URL configuration, you should specify pathname as a separate configuration option (as it would be considered as the database otherwise).
  • (TypeScript only) ResultSet and Row are now more strictly typed, according to the format used during the query call.
  • (TypeScript only) Both Node.js and Web versions now uniformly export correct ClickHouseClient and ClickHouseClientConfigOptions types specific to each implementation. Exported ClickHouseClient now does not have a Stream type parameter, as it was unintended to expose it there. NB: you should still use the createClient factory function provided in the package.

New features in 1.0.0

Advanced TypeScript support for query + ResultSet

The client will now try its best to figure out the shape of the data based on the DataFormat literal specified to the query call, as well as which methods are allowed to be called on the ResultSet.

Live demo (see the full description below):

Screencast.from.2024-03-09.08-10-26.webm

Complete reference:

Format ResultSet.json<T>() ResultSet.stream<T>() Stream data Row.json<T>()
JSON ResponseJSON<T> never never never
JSONObjectEachRow Record<string, T> never never never
All other JSON*EachRow Array<T> Stream<Array<Row<T>>> Array<Row<T>> T
CSV/TSV/CustomSeparated/Parquet never Stream<Array<Row<T>>> Array<Row<T>> never

By default, T (which represents JSONType) is still unknown. However, considering the JSONObjectsEachRow example, prior to 1.0.0, you had to specify the entire type hint, including the shape of the data, manually:

type Data = { foo: string }

const resultSet = await client.query({
  query: 'SELECT * FROM my_table',
  format: 'JSONObjectsEachRow',
})

// pre-1.0.0, `resultOld` has type Record<string, Data>
const resultOld = resultSet.json<Record<string, Data>>()
// const resultOld = resultSet.json<Data>() // incorrect! The type hint should've been `Record<string, Data>` here.

// 1.0.0, `resultNew` also has type Record<string, Data>; the client inferred that it has to be a Record from the format literal.
const resultNew = resultSet.json<Data>()

This is even more handy in the case of streaming on the Node.js platform:

const resultSet = await client.query({
  query: 'SELECT * FROM my_table',
  format: 'JSONEachRow',
})

// pre-1.0.0
// `streamOld` was just a regular Node.js Stream.Readable
const streamOld = resultSet.stream()
// `rows` were `any`, needed an explicit type hint
streamNew.on('data', (rows: Row[]) => {
  rows.forEach((row) => {
    // without an explicit type hint to `rows`, calling `forEach` and other array methods resulted in TS compiler errors
    const t = row.text
    const j = row.json<Data>() // `j` needed a type hint here, otherwise, it's `unknown`
  })
})

// 1.0.0
// `streamNew` is now StreamReadable<T> (Node.js Stream.Readable with a bit more type hints);
// type hint for the further `json` calls can be added here (and removed from the `json` calls)
const streamNew = resultSet.stream<Data>()
// `rows` are inferred as an Array<Row<Data, "JSONEachRow">> instead of `any`
streamNew.on('data', (rows) => {
  // `row` is inferred as Row<Data, "JSONEachRow">
  rows.forEach((row) => {
    // no explicit type hints required, you can use `forEach` straight away and TS compiler will be happy
    const t = row.text
    const j = row.json() // `j` will be of type Data
  })
})

// async iterator now also has type hints
//Similarly to the `on(data)` example above, `rows` are inferred as Array<Row<Data, "JSONEachRow">>
for await (const rows of streamNew) {
  // `row` is inferred as Row<Data, "JSONEachRow">
  rows.forEach((row) => {
    const t = row.text
    const j = row.json() // `j` will be of type Data
  })
}

Calling ResultSet.stream is not allowed for specific data formats, such as JSON and JSONObjectsEachRow (unlike JSONEachRow and the rest of JSON*EachRow, these formats return a single object). In these cases, the client throws an error. However, it was previously not reflected on the type level; now, calling stream on these formats will result in a TS compiler error. For example:

const resultSet = await client.query('SELECT * FROM table', {
  format: 'JSON',
})
const stream = resultSet.stream() // `stream` is `never`

Calling ResultSet.json also does not make sense on CSV and similar "raw" formats, and the client throws. Again, now, it is typed properly:

const resultSet = await client.query('SELECT * FROM table', {
  format: 'CSV',
})
// `json` is `never`; same if you stream CSV, and call `Row.json` - it will be `never`, too.
const json = resultSet.json()

Currently, there is one known limitation: as the general shape of the data and the methods allowed for calling are inferred from the format literal, there might be situations where it will fail to do so, for example:

// assuming that `queryParams` has `JSONObjectsEachRow` format inside
async function runQuery(
  queryParams: QueryParams,
): Promise<Record<string, Data>> {
  const resultSet = await client.query(queryParams)
  // type hint here will provide a union of all known shapes instead of a specific one
  // inferred shapes: Data[] | ResponseJSON<Data> | Record<string, Data>
  return resultSet.json<Data>()
}

In this case, as it is likely that you already know the desired format in advance (otherwise, returning a specific shape like Record<string, Data> would've been incorrect), consider helping the client a bit:

async function runQuery(
  queryParams: QueryParams,
): Promise<Record<string, Data>> {
  const resultSet = await client.query({
    ...queryParams,
    format: 'JSONObjectsEachRow',
  })
  // TS understands that it is a Record<string, Data> now
  return resultSet.json<Data>()
}

If you are interested in more details, see the related test (featuring a great ESLint plugin expect-types) in the client package.

URL configuration

  • Added url configuration parameter. It is intended to replace the deprecated host, which was already supposed to be passed as a valid URL.
  • It is now possible to configure most of the client instance parameters with a URL. The URL format is http[s]://[username:password@]hostname:port[/database][?param1=value1&param2=value2]. In almost every case, the name of a particular parameter reflects its path in the config options interface, with a few exceptions. The following parameters are supported:
Parameter Type
pathname an arbitrary string.
application_id an arbitrary string.
session_id an arbitrary string.
request_timeout non-negative number.
max_open_connections non-negative number, greater than zero.
compression_request boolean. See below [1].
compression_response boolean.
log_level allowed values: OFF, TRACE, DEBUG, INFO, WARN, ERROR.
keep_alive_enabled boolean.
clickhouse_setting_* or ch_* see be...
Read more