@clickhouse/client 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/dist/client.d.ts +6 -6
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +6 -6
- package/dist/config.js +6 -5
- package/dist/config.js.map +1 -1
- package/dist/connection/compression.d.ts +4 -4
- package/dist/connection/compression.js +3 -3
- package/dist/connection/compression.js.map +1 -1
- package/dist/connection/create_connection.d.ts +6 -6
- package/dist/connection/create_connection.js +3 -3
- package/dist/connection/create_connection.js.map +1 -1
- package/dist/connection/index.d.ts +4 -4
- package/dist/connection/index.js.map +1 -1
- package/dist/connection/node_base_connection.d.ts +11 -11
- package/dist/connection/node_base_connection.js +75 -42
- package/dist/connection/node_base_connection.js.map +1 -1
- package/dist/connection/node_custom_agent_connection.d.ts +4 -4
- package/dist/connection/node_custom_agent_connection.js +2 -2
- package/dist/connection/node_custom_agent_connection.js.map +1 -1
- package/dist/connection/node_http_connection.d.ts +4 -4
- package/dist/connection/node_http_connection.js.map +1 -1
- package/dist/connection/node_https_connection.d.ts +5 -5
- package/dist/connection/node_https_connection.js +11 -11
- package/dist/connection/node_https_connection.js.map +1 -1
- package/dist/connection/socket_pool.d.ts +9 -9
- package/dist/connection/socket_pool.js +33 -32
- package/dist/connection/socket_pool.js.map +1 -1
- package/dist/connection/stream.d.ts +2 -2
- package/dist/connection/stream.js +18 -18
- package/dist/connection/stream.js.map +1 -1
- package/dist/index.d.ts +41 -8
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/result_set.d.ts +31 -20
- package/dist/result_set.js +83 -13
- package/dist/result_set.js.map +1 -1
- package/dist/utils/encoder.d.ts +2 -2
- package/dist/utils/encoder.js +3 -3
- package/dist/utils/encoder.js.map +1 -1
- package/dist/utils/index.d.ts +4 -4
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/process.js.map +1 -1
- package/dist/utils/runtime.js.map +1 -1
- package/dist/utils/stream.d.ts +1 -1
- package/dist/utils/stream.js +8 -8
- package/dist/utils/stream.js.map +1 -1
- package/dist/utils/user_agent.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +2 -2
- package/skills/clickhouse-js-node-coding/reference/async-insert.md +12 -12
- package/skills/clickhouse-js-node-coding/reference/client-configuration.md +16 -16
- package/skills/clickhouse-js-node-coding/reference/custom-json.md +31 -31
- package/skills/clickhouse-js-node-coding/reference/data-types.md +65 -65
- package/skills/clickhouse-js-node-coding/reference/insert-columns.md +23 -23
- package/skills/clickhouse-js-node-coding/reference/insert-formats.md +30 -30
- package/skills/clickhouse-js-node-coding/reference/insert-values.md +35 -35
- package/skills/clickhouse-js-node-coding/reference/ping.md +24 -24
- package/skills/clickhouse-js-node-coding/reference/query-parameters.md +27 -27
- package/skills/clickhouse-js-node-coding/reference/select-formats.md +21 -21
- package/skills/clickhouse-js-node-coding/reference/sessions.md +27 -27
- package/skills/clickhouse-js-node-troubleshooting/reference/compression.md +2 -2
- package/skills/clickhouse-js-node-troubleshooting/reference/data-types.md +24 -24
- package/skills/clickhouse-js-node-troubleshooting/reference/logging.md +5 -5
- package/skills/clickhouse-js-node-troubleshooting/reference/proxy-pathname.md +7 -7
- package/skills/clickhouse-js-node-troubleshooting/reference/query-format-clause.md +6 -6
- package/skills/clickhouse-js-node-troubleshooting/reference/query-params.md +30 -30
- package/skills/clickhouse-js-node-troubleshooting/reference/readonly-users.md +4 -4
- package/skills/clickhouse-js-node-troubleshooting/reference/socket-hangup.md +20 -20
- package/skills/clickhouse-js-node-troubleshooting/reference/tls.md +24 -24
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
**Fix:** Use the `pathname` option separately:
|
|
10
10
|
|
|
11
11
|
```js
|
|
12
|
-
import { createClient } from
|
|
12
|
+
import { createClient } from "@clickhouse/client";
|
|
13
13
|
|
|
14
14
|
const client = createClient({
|
|
15
|
-
url:
|
|
16
|
-
pathname:
|
|
17
|
-
})
|
|
15
|
+
url: "http://proxy:8123",
|
|
16
|
+
pathname: "/clickhouse_server", // leading slash optional; multiple segments supported
|
|
17
|
+
});
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
For proxies that require custom auth headers:
|
|
@@ -22,11 +22,11 @@ For proxies that require custom auth headers:
|
|
|
22
22
|
> **Requires:** `>= 1.0.0` (`http_headers` config option; replaces the deprecated `additional_headers` from `>= 0.2.9`). Per-request `http_headers` overrides are available since `>= 1.11.0`.
|
|
23
23
|
|
|
24
24
|
```js
|
|
25
|
-
import { createClient } from
|
|
25
|
+
import { createClient } from "@clickhouse/client";
|
|
26
26
|
|
|
27
27
|
const client = createClient({
|
|
28
28
|
http_headers: {
|
|
29
|
-
|
|
29
|
+
"My-Auth-Header": "secret",
|
|
30
30
|
},
|
|
31
|
-
})
|
|
31
|
+
});
|
|
32
32
|
```
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
```js
|
|
8
8
|
// What you write:
|
|
9
|
-
await client.query({ query:
|
|
9
|
+
await client.query({ query: "SELECT 1", format: "JSONEachRow" });
|
|
10
10
|
|
|
11
11
|
// What the client actually sends:
|
|
12
12
|
// SELECT 1
|
|
@@ -19,10 +19,10 @@ If the `query` string already contains a `FORMAT` clause, the client still appen
|
|
|
19
19
|
|
|
20
20
|
```js
|
|
21
21
|
// ❌ Wrong — ends up as `... FORMAT CSV FORMAT JSON` → syntax error
|
|
22
|
-
await client.query({ query:
|
|
22
|
+
await client.query({ query: "SELECT 1 FORMAT CSV" });
|
|
23
23
|
|
|
24
24
|
// ✓ Correct — let the client append FORMAT via the option
|
|
25
|
-
await client.query({ query:
|
|
25
|
+
await client.query({ query: "SELECT 1", format: "CSV" });
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
If you genuinely need to write the full SQL yourself (including the `FORMAT` clause), or you're running a statement where the appended `FORMAT` suffix is not supported, use `client.exec()` instead of `client.query()`. Use `client.insert()` for data insertion and `client.command()` for DDLs.
|
|
@@ -33,15 +33,15 @@ Some statements are not parsed by the server with a trailing `FORMAT` clause, so
|
|
|
33
33
|
|
|
34
34
|
```js
|
|
35
35
|
// ❌ Fails — query() appends `FORMAT JSON`, which the short SHOW POLICIES syntax rejects
|
|
36
|
-
await client.query({ query:
|
|
37
|
-
await client.query({ query:
|
|
36
|
+
await client.query({ query: "SHOW POLICIES", format: "JSON" });
|
|
37
|
+
await client.query({ query: "SHOW ROW POLICIES", format: "JSON" });
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
**Fix:** use the full syntax `SHOW POLICIES ON *` (or `SHOW POLICIES ON db.table`), which the parser accepts together with the appended `FORMAT`:
|
|
41
41
|
|
|
42
42
|
```js
|
|
43
43
|
// ✓ Works — full syntax accepts the appended FORMAT clause
|
|
44
|
-
await client.query({ query:
|
|
44
|
+
await client.query({ query: "SHOW POLICIES ON *", format: "JSON" });
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Alternatively, run the short statement through `client.exec()`, where you control the full SQL and no `FORMAT` suffix is appended.
|
|
@@ -6,10 +6,10 @@ Use the `{name: type}` syntax in the query string and pass values via `query_par
|
|
|
6
6
|
|
|
7
7
|
```js
|
|
8
8
|
await client.query({
|
|
9
|
-
query:
|
|
10
|
-
format:
|
|
9
|
+
query: "SELECT plus({val1: Int32}, {val2: Int32})",
|
|
10
|
+
format: "CSV",
|
|
11
11
|
query_params: { val1: 10, val2: 20 },
|
|
12
|
-
})
|
|
12
|
+
});
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Never use template literals for user values
|
|
@@ -18,14 +18,14 @@ When `$1`/`?` don't work, a common instinct is to interpolate values directly wi
|
|
|
18
18
|
|
|
19
19
|
```js
|
|
20
20
|
// ❌ Dangerous — never do this with user-controlled values
|
|
21
|
-
const userId = req.params.id
|
|
22
|
-
await client.query({ query: `SELECT * FROM users WHERE id = ${userId}` })
|
|
21
|
+
const userId = req.params.id;
|
|
22
|
+
await client.query({ query: `SELECT * FROM users WHERE id = ${userId}` });
|
|
23
23
|
|
|
24
24
|
// ✓ Safe — parameterized
|
|
25
25
|
await client.query({
|
|
26
|
-
query:
|
|
26
|
+
query: "SELECT * FROM users WHERE id = {id: UInt32}",
|
|
27
27
|
query_params: { id: userId },
|
|
28
|
-
})
|
|
28
|
+
});
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
Always bring this up when answering query-params questions, especially when the user is coming from another database (PostgreSQL, MySQL, etc.) — they're the most likely to reach for template literals as a fallback.
|
|
@@ -37,27 +37,27 @@ The ClickHouse JS client uses ClickHouse's native `{name: type}` syntax — not
|
|
|
37
37
|
```js
|
|
38
38
|
// ❌ Wrong — these don't work
|
|
39
39
|
await client.query({
|
|
40
|
-
query:
|
|
41
|
-
query:
|
|
42
|
-
query:
|
|
40
|
+
query: "SELECT * FROM t WHERE id = $1",
|
|
41
|
+
query: "SELECT * FROM t WHERE id = ?",
|
|
42
|
+
query: "SELECT * FROM t WHERE id = :id",
|
|
43
43
|
query_params: { id: 42 },
|
|
44
|
-
})
|
|
44
|
+
});
|
|
45
45
|
|
|
46
46
|
// ✓ Correct
|
|
47
47
|
await client.query({
|
|
48
|
-
query:
|
|
48
|
+
query: "SELECT * FROM t WHERE id = {id: UInt32}",
|
|
49
49
|
query_params: { id: 42 },
|
|
50
|
-
})
|
|
50
|
+
});
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
## Array parameters
|
|
54
54
|
|
|
55
55
|
```js
|
|
56
56
|
await client.query({
|
|
57
|
-
query:
|
|
58
|
-
format:
|
|
57
|
+
query: "SELECT * FROM t WHERE id IN {ids: Array(UInt32)}",
|
|
58
|
+
format: "JSONEachRow",
|
|
59
59
|
query_params: { ids: [1, 2, 3] },
|
|
60
|
-
})
|
|
60
|
+
});
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
## Tuple parameters (`>= 1.9.0`)
|
|
@@ -65,17 +65,17 @@ await client.query({
|
|
|
65
65
|
Use the `TupleParam` wrapper to pass a tuple:
|
|
66
66
|
|
|
67
67
|
```js
|
|
68
|
-
import { TupleParam, createClient } from
|
|
68
|
+
import { TupleParam, createClient } from "@clickhouse/client";
|
|
69
69
|
|
|
70
70
|
const client = createClient({
|
|
71
|
-
url:
|
|
72
|
-
})
|
|
71
|
+
url: "http://localhost:8123",
|
|
72
|
+
});
|
|
73
73
|
|
|
74
74
|
await client.query({
|
|
75
|
-
query:
|
|
76
|
-
format:
|
|
77
|
-
query_params: { t: new TupleParam([42,
|
|
78
|
-
})
|
|
75
|
+
query: "SELECT {t: Tuple(UInt32, String)}",
|
|
76
|
+
format: "JSONEachRow",
|
|
77
|
+
query_params: { t: new TupleParam([42, "hello"]) },
|
|
78
|
+
});
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
## Map parameters (`>= 1.9.0`)
|
|
@@ -84,10 +84,10 @@ Pass a JS `Map` directly:
|
|
|
84
84
|
|
|
85
85
|
```js
|
|
86
86
|
await client.query({
|
|
87
|
-
query:
|
|
88
|
-
format:
|
|
89
|
-
query_params: { m: new Map([[
|
|
90
|
-
})
|
|
87
|
+
query: "SELECT {m: Map(String, UInt32)}",
|
|
88
|
+
format: "JSONEachRow",
|
|
89
|
+
query_params: { m: new Map([["key", 1]]) },
|
|
90
|
+
});
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
## NULL parameters
|
|
@@ -96,8 +96,8 @@ Pass `null` directly — binding fixed in `0.0.16`:
|
|
|
96
96
|
|
|
97
97
|
```js
|
|
98
98
|
await client.query({
|
|
99
|
-
query:
|
|
100
|
-
format:
|
|
99
|
+
query: "SELECT {val: Nullable(String)}",
|
|
100
|
+
format: "JSONEachRow",
|
|
101
101
|
query_params: { val: null },
|
|
102
|
-
})
|
|
102
|
+
});
|
|
103
103
|
```
|
|
@@ -9,17 +9,17 @@
|
|
|
9
9
|
**Fix:** Remove response compression for read-only users:
|
|
10
10
|
|
|
11
11
|
```js
|
|
12
|
-
import { createClient } from
|
|
12
|
+
import { createClient } from "@clickhouse/client";
|
|
13
13
|
|
|
14
14
|
// Don't do this with a readonly=1 user:
|
|
15
15
|
// compression: { response: true }
|
|
16
16
|
|
|
17
17
|
const client = createClient({
|
|
18
|
-
username:
|
|
19
|
-
password:
|
|
18
|
+
username: "my_readonly_user",
|
|
19
|
+
password: "...",
|
|
20
20
|
// compression omitted, or explicitly set to false
|
|
21
21
|
compression: {
|
|
22
22
|
response: false,
|
|
23
23
|
},
|
|
24
|
-
})
|
|
24
|
+
});
|
|
25
25
|
```
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
> **Requires:** `>= 0.2.0` (logging support with `log.level` config option). In `>= 1.18.1`, the default log level changed from `OFF` to `WARN`, so this step may already be active. In `>= 1.18.2`, the client auto-emits a WARN log with Keep-Alive troubleshooting hints when an `ECONNRESET` is detected. In `>= 1.12.0`, a warning is logged when a socket is closed without fully consuming the stream.
|
|
17
17
|
|
|
18
18
|
```js
|
|
19
|
-
import { createClient, ClickHouseLogLevel } from
|
|
19
|
+
import { createClient, ClickHouseLogLevel } from "@clickhouse/client";
|
|
20
20
|
|
|
21
21
|
const client = createClient({
|
|
22
22
|
log: { level: ClickHouseLogLevel.WARN },
|
|
23
|
-
})
|
|
23
|
+
});
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Look for log lines about unconsumed or dangling streams — these are a common hidden cause. A **dangling stream** is a query response stream that was never fully consumed or explicitly closed with `ResultSet.close()`. Because the Node.js client reuses sockets (Keep-Alive), leaving a stream open corrupts the socket and causes the _next_ request to fail with `ECONNRESET`. Errors on **every request** strongly suggest dangling streams rather than a Keep-Alive timeout mismatch.
|
|
@@ -29,33 +29,33 @@ Look for log lines about unconsumed or dangling streams — these are a common h
|
|
|
29
29
|
|
|
30
30
|
```js
|
|
31
31
|
// ❌ Wrong — result stream never consumed; socket is left open
|
|
32
|
-
const resultSet = await client.query({ query:
|
|
32
|
+
const resultSet = await client.query({ query: "SELECT ..." });
|
|
33
33
|
// result is abandoned without calling .json(), .text(), .stream(), or .close()
|
|
34
34
|
|
|
35
35
|
// ❌ Wrong — stream created but not fully piped/iterated
|
|
36
36
|
const resultSet = await client.query({
|
|
37
|
-
query:
|
|
38
|
-
format:
|
|
39
|
-
})
|
|
40
|
-
const stream = resultSet.stream()
|
|
37
|
+
query: "SELECT ...",
|
|
38
|
+
format: "JSONEachRow",
|
|
39
|
+
});
|
|
40
|
+
const stream = resultSet.stream();
|
|
41
41
|
// stream is never iterated and resultSet is never closed
|
|
42
42
|
|
|
43
43
|
// ✓ Correct — consume via .json()
|
|
44
|
-
const resultSet = await client.query({ query:
|
|
45
|
-
const data = await resultSet.json()
|
|
44
|
+
const resultSet = await client.query({ query: "SELECT ..." });
|
|
45
|
+
const data = await resultSet.json();
|
|
46
46
|
|
|
47
47
|
// ✓ Correct — consume via async iteration
|
|
48
48
|
const resultSet = await client.query({
|
|
49
|
-
query:
|
|
50
|
-
format:
|
|
51
|
-
})
|
|
49
|
+
query: "SELECT ...",
|
|
50
|
+
format: "JSONEachRow",
|
|
51
|
+
});
|
|
52
52
|
for await (const rows of resultSet.stream()) {
|
|
53
53
|
// process rows
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// ✓ Correct — explicitly close; this destroys the underlying socket immediately
|
|
57
|
-
const resultSet = await client.query({ query:
|
|
58
|
-
resultSet.close()
|
|
57
|
+
const resultSet = await client.query({ query: "SELECT ..." });
|
|
58
|
+
resultSet.close();
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
## Step 2 — Check your ESLint setup
|
|
@@ -86,7 +86,7 @@ const client = createClient({
|
|
|
86
86
|
keep_alive: {
|
|
87
87
|
idle_socket_ttl: 9000, // stay ~500ms below the server's timeout
|
|
88
88
|
},
|
|
89
|
-
})
|
|
89
|
+
});
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
> ⚠️ If you still get errors after increasing, **lower** the value, not raise it.
|
|
@@ -104,9 +104,9 @@ const client = createClient({
|
|
|
104
104
|
request_timeout: 400_000, // e.g. 400s for long queries
|
|
105
105
|
clickhouse_settings: {
|
|
106
106
|
send_progress_in_http_headers: 1,
|
|
107
|
-
http_headers_progress_interval_ms:
|
|
107
|
+
http_headers_progress_interval_ms: "110000", // string — UInt64 type; set ~10s below LB idle timeout
|
|
108
108
|
},
|
|
109
|
-
})
|
|
109
|
+
});
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
### ⚠️ Critical: 16 KB Node.js Header Size Limit
|
|
@@ -140,9 +140,9 @@ const client = createClient({
|
|
|
140
140
|
max_response_headers_size: 65536, // 64 KB; lifts the per-request header cap
|
|
141
141
|
clickhouse_settings: {
|
|
142
142
|
send_progress_in_http_headers: 1,
|
|
143
|
-
http_headers_progress_interval_ms:
|
|
143
|
+
http_headers_progress_interval_ms: "110000",
|
|
144
144
|
},
|
|
145
|
-
})
|
|
145
|
+
});
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
```bash
|
|
@@ -200,5 +200,5 @@ Adds overhead (new TCP connection per request) but eliminates all Keep-Alive iss
|
|
|
200
200
|
```js
|
|
201
201
|
const client = createClient({
|
|
202
202
|
keep_alive: { enabled: false },
|
|
203
|
-
})
|
|
203
|
+
});
|
|
204
204
|
```
|
|
@@ -5,34 +5,34 @@
|
|
|
5
5
|
## Basic TLS (CA certificate only)
|
|
6
6
|
|
|
7
7
|
```js
|
|
8
|
-
import fs from
|
|
9
|
-
import { createClient } from
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import { createClient } from "@clickhouse/client";
|
|
10
10
|
|
|
11
11
|
const client = createClient({
|
|
12
|
-
url:
|
|
13
|
-
username:
|
|
14
|
-
password:
|
|
12
|
+
url: "https://<hostname>:<port>",
|
|
13
|
+
username: "<user>",
|
|
14
|
+
password: "<pass>",
|
|
15
15
|
tls: {
|
|
16
|
-
ca_cert: fs.readFileSync(
|
|
16
|
+
ca_cert: fs.readFileSync("certs/CA.pem"),
|
|
17
17
|
},
|
|
18
|
-
})
|
|
18
|
+
});
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Mutual TLS (client certificate + key)
|
|
22
22
|
|
|
23
23
|
```js
|
|
24
|
-
import fs from
|
|
25
|
-
import { createClient } from
|
|
24
|
+
import fs from "fs";
|
|
25
|
+
import { createClient } from "@clickhouse/client";
|
|
26
26
|
|
|
27
27
|
const client = createClient({
|
|
28
|
-
url:
|
|
29
|
-
username:
|
|
28
|
+
url: "https://<hostname>:<port>",
|
|
29
|
+
username: "<user>",
|
|
30
30
|
tls: {
|
|
31
|
-
ca_cert: fs.readFileSync(
|
|
32
|
-
cert: fs.readFileSync(
|
|
33
|
-
key: fs.readFileSync(
|
|
31
|
+
ca_cert: fs.readFileSync("certs/CA.pem"),
|
|
32
|
+
cert: fs.readFileSync("certs/client.crt"),
|
|
33
|
+
key: fs.readFileSync("certs/client.key"),
|
|
34
34
|
},
|
|
35
|
-
})
|
|
35
|
+
});
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
> **Tip (`>= 1.2.0`):** If you need a custom HTTP(S) agent, use the `http_agent` option. Only set `set_basic_auth_header: false` if you must avoid sending the basic-auth `Authorization` header (for example, due to a header conflict); in that case, provide alternative auth headers such as `X-ClickHouse-User` / `X-ClickHouse-Key` via `http_headers`.
|
|
@@ -59,29 +59,29 @@ The server uses a self-signed cert (the certificate is its own CA). Options in o
|
|
|
59
59
|
|
|
60
60
|
```js
|
|
61
61
|
tls: {
|
|
62
|
-
ca_cert: fs.readFileSync(
|
|
62
|
+
ca_cert: fs.readFileSync("certs/server.crt");
|
|
63
63
|
}
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
2. For development only — disable verification via a custom agent (`>= 1.2.0`):
|
|
67
67
|
|
|
68
68
|
```js
|
|
69
|
-
import https from
|
|
70
|
-
import { createClient } from
|
|
69
|
+
import https from "https";
|
|
70
|
+
import { createClient } from "@clickhouse/client";
|
|
71
71
|
|
|
72
72
|
const client = createClient({
|
|
73
|
-
url:
|
|
74
|
-
username:
|
|
75
|
-
password:
|
|
73
|
+
url: "https://<hostname>:<port>",
|
|
74
|
+
username: "<user>",
|
|
75
|
+
password: "<pass>",
|
|
76
76
|
http_agent: new https.Agent({ rejectUnauthorized: false }),
|
|
77
77
|
// Optional: only disable the basic-auth Authorization header if you need to
|
|
78
78
|
// provide alternative auth headers instead.
|
|
79
79
|
set_basic_auth_header: false,
|
|
80
80
|
http_headers: {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
"X-ClickHouse-User": "<user>",
|
|
82
|
+
"X-ClickHouse-Key": "<pass>",
|
|
83
83
|
},
|
|
84
|
-
})
|
|
84
|
+
});
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
> ⚠️ Never use `rejectUnauthorized: false` in production — it disables all certificate verification.
|