@clickhouse/client 1.23.0-head.287977a.1 → 1.23.0-head.71b2e8a.1

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +1350 -0
  2. package/README.md +36 -91
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.js +3 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/version.d.ts +1 -1
  7. package/dist/version.js +1 -1
  8. package/package.json +18 -7
  9. package/skills/AGENTS.md +8 -0
  10. package/skills/clickhouse-js-node-rowbinary/AGENTS.md +44 -0
  11. package/skills/clickhouse-js-node-rowbinary/CHANGELOG.md +49 -0
  12. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/README.md +78 -14
  13. package/skills/clickhouse-js-node-rowbinary/SKILL.md +111 -0
  14. package/skills/{clickhouse-js-node-rowbinary-parser/SKILL.md → clickhouse-js-node-rowbinary/reader.md} +51 -131
  15. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/carts.ts +9 -5
  16. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/events.ts +5 -5
  17. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/iot.ts +4 -4
  18. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/ledger.ts +3 -3
  19. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/logs.ts +4 -4
  20. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/observability.ts +9 -10
  21. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/orders.ts +10 -9
  22. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/profiles.ts +5 -5
  23. package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/src/examples/telemetry.ts +6 -6
  24. package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/compile.ts +18 -8
  25. package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/dynamic.ts +12 -8
  26. package/skills/clickhouse-js-node-rowbinary/src/readers/enums.ts +40 -0
  27. package/skills/clickhouse-js-node-rowbinary/src/writers/aggregateFunction.ts +18 -0
  28. package/skills/clickhouse-js-node-rowbinary/src/writers/bool.ts +10 -0
  29. package/skills/clickhouse-js-node-rowbinary/src/writers/composite.ts +140 -0
  30. package/skills/clickhouse-js-node-rowbinary/src/writers/core.ts +92 -0
  31. package/skills/clickhouse-js-node-rowbinary/src/writers/datetime.ts +123 -0
  32. package/skills/clickhouse-js-node-rowbinary/src/writers/decimals.ts +51 -0
  33. package/skills/clickhouse-js-node-rowbinary/src/writers/enums.ts +18 -0
  34. package/skills/clickhouse-js-node-rowbinary/src/writers/floats.ts +40 -0
  35. package/skills/clickhouse-js-node-rowbinary/src/writers/geo.ts +125 -0
  36. package/skills/clickhouse-js-node-rowbinary/src/writers/integers.ts +90 -0
  37. package/skills/clickhouse-js-node-rowbinary/src/writers/interval.ts +11 -0
  38. package/skills/clickhouse-js-node-rowbinary/src/writers/ip.ts +121 -0
  39. package/skills/clickhouse-js-node-rowbinary/src/writers/lowCardinality.ts +12 -0
  40. package/skills/clickhouse-js-node-rowbinary/src/writers/nested.ts +17 -0
  41. package/skills/clickhouse-js-node-rowbinary/src/writers/nothing.ts +21 -0
  42. package/skills/clickhouse-js-node-rowbinary/src/writers/rows.ts +144 -0
  43. package/skills/clickhouse-js-node-rowbinary/src/writers/simpleAggregateFunction.ts +12 -0
  44. package/skills/clickhouse-js-node-rowbinary/src/writers/strings.ts +77 -0
  45. package/skills/clickhouse-js-node-rowbinary/src/writers/time.ts +54 -0
  46. package/skills/clickhouse-js-node-rowbinary/src/writers/uuid.ts +60 -0
  47. package/skills/clickhouse-js-node-rowbinary/src/writers/varint.ts +64 -0
  48. package/skills/clickhouse-js-node-rowbinary/src/writers/writer.ts +101 -0
  49. package/skills/clickhouse-js-node-rowbinary/writer.md +96 -0
  50. package/skills/clickhouse-js-node-rowbinary-parser/src/enums.ts +0 -28
  51. /package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/EXAMPLES.md +0 -0
  52. /package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/case-studies/iot-rowbinary-vs-json.md +0 -0
  53. /package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/case-studies/ledger-rowbinary-vs-json.md +0 -0
  54. /package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/case-studies/logs-json-wins.md +0 -0
  55. /package/skills/{clickhouse-js-node-rowbinary-parser → clickhouse-js-node-rowbinary}/case-studies/wasm-vs-js.md +0 -0
  56. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/aggregateFunction.ts +0 -0
  57. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/bool.ts +0 -0
  58. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/columnar.ts +0 -0
  59. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/composite.ts +0 -0
  60. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/core.ts +0 -0
  61. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/datetime.ts +0 -0
  62. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/decimals.ts +0 -0
  63. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/floats.ts +0 -0
  64. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/geo.ts +0 -0
  65. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/header.ts +0 -0
  66. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/integers.ts +0 -0
  67. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/interval.ts +0 -0
  68. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/ip.ts +0 -0
  69. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/json.ts +0 -0
  70. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/lowCardinality.ts +0 -0
  71. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/nested.ts +0 -0
  72. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/nothing.ts +0 -0
  73. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/reader.ts +0 -0
  74. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/rowBinaryWithNamesAndTypes.ts +0 -0
  75. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/rows.ts +0 -0
  76. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/simpleAggregateFunction.ts +0 -0
  77. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/stream.ts +0 -0
  78. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/strings.ts +0 -0
  79. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/time.ts +0 -0
  80. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/uuid.ts +0 -0
  81. /package/skills/{clickhouse-js-node-rowbinary-parser/src → clickhouse-js-node-rowbinary/src/readers}/varint.ts +0 -0
package/README.md CHANGED
@@ -1,78 +1,39 @@
1
- <p align="center">
2
- <img src=".static/logo.svg" width="200px" align="center">
3
- <h1 align="center">ClickHouse JS client</h1>
4
- </p>
5
- <br/>
6
- <p align="center">
7
- <a href="https://www.npmjs.com/package/@clickhouse/client">
8
- <img alt="NPM Version" src="https://img.shields.io/npm/v/%40clickhouse%2Fclient?color=%233178C6&logo=npm">
9
- </a>
1
+ # @clickhouse/client
10
2
 
11
- <a href="https://www.npmjs.com/package/@clickhouse/client">
12
- <img alt="NPM Downloads" src="https://img.shields.io/npm/dw/%40clickhouse%2Fclient?color=%233178C6&logo=npm">
13
- </a>
3
+ Official Node.js client for [ClickHouse](https://clickhouse.com/), written
4
+ purely in TypeScript and thoroughly tested against actual ClickHouse versions.
14
5
 
15
- <a href="https://github.com/ClickHouse/clickhouse-js/actions/workflows/tests-node.yml">
16
- <img src="https://github.com/ClickHouse/clickhouse-js/actions/workflows/tests-node.yml/badge.svg?branch=main">
17
- </a>
6
+ It is built on top of the Node.js [HTTP](https://nodejs.org/api/http.html) and
7
+ [Stream](https://nodejs.org/api/stream.html) APIs and supports streaming for
8
+ both selects and inserts. The client has zero external dependencies and is
9
+ optimized for maximum performance.
18
10
 
19
- <a href="https://github.com/ClickHouse/clickhouse-js/actions/workflows/tests-web.yml">
20
- <img src="https://github.com/ClickHouse/clickhouse-js/actions/workflows/tests-web.yml/badge.svg?branch=main">
21
- </a>
22
-
23
- <a href="https://codecov.io/gh/ClickHouse/clickhouse-js">
24
- <img src="https://codecov.io/gh/ClickHouse/clickhouse-js/graph/badge.svg?token=B832WB00WJ">
25
- </a>
26
-
27
- <img src="https://api.scorecard.dev/projects/github.com/ClickHouse/clickhouse-js/badge">
28
- </p>
29
-
30
- ## About
31
-
32
- Official JS client for [ClickHouse](https://clickhouse.com/), written purely in TypeScript, thoroughly tested with actual ClickHouse versions.
33
-
34
- The client has zero external dependencies and is optimized for maximum performance.
35
-
36
- The repository consists of four packages:
37
-
38
- - `@clickhouse/client` - a version of the client designed for Node.js platform only. It is built on top of [HTTP](https://nodejs.org/api/http.html)
39
- and [Stream](https://nodejs.org/api/stream.html) APIs; supports streaming for both selects and inserts.
40
- - `@clickhouse/client-web` - a version of the client built on top of [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
41
- and [Web Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) APIs; supports streaming for selects.
42
- Compatible with Chrome/Firefox browsers and Cloudflare workers.
43
- - `@clickhouse/client-common` - shared common types and the base framework for building a custom client implementation.
44
- - `@clickhouse/rowbinary` - a library for reading (and soon writing) ClickHouse RowBinary format.
11
+ > Looking for a browser / edge runtime (Cloudflare Workers, etc.) instead? Use
12
+ > [`@clickhouse/client-web`](https://www.npmjs.com/package/@clickhouse/client-web).
45
13
 
46
14
  ## Installation
47
15
 
48
- Node.js client:
49
-
50
16
  ```sh
51
17
  npm i @clickhouse/client
52
18
  ```
53
19
 
54
- Web client (browsers, Cloudflare workers):
55
-
56
- ```sh
57
- npm i @clickhouse/client-web
58
- ```
59
-
60
20
  ## Environment requirements
61
21
 
62
- ### Node.js
22
+ Node.js must be available in the environment to run the client. The client is
23
+ compatible with all the [maintained](https://github.com/nodejs/release#readme)
24
+ Node.js releases.
63
25
 
64
- Node.js must be available in the environment to run the Node.js client. The client is compatible with all the [maintained](https://github.com/nodejs/release#readme) Node.js releases.
26
+ | Node.js version | Supported? |
27
+ | --------------- | ---------- |
28
+ | 26.x | ✔ |
29
+ | 24.x | ✔ |
30
+ | 22.x | ✔ |
31
+ | 20.x | ✔ |
65
32
 
66
- | Node.js version | Supported? |
67
- | --------------- | ----------- |
68
- | 24.x | ✔ |
69
- | 22.x | ✔ |
70
- | 20.x | ✔ |
71
- | 18.x | Best effort |
72
-
73
- ### TypeScript
74
-
75
- If using TypeScript, version [4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) or above is required to enable [inline import and export syntax](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names).
33
+ If using TypeScript, version
34
+ [4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html)
35
+ or above is required to enable
36
+ [inline import and export syntax](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names).
76
37
 
77
38
  ## Compatibility with ClickHouse
78
39
 
@@ -80,12 +41,13 @@ If using TypeScript, version [4.5](https://www.typescriptlang.org/docs/handbook/
80
41
  | -------------- | ---------- |
81
42
  | 1.12.0+ | 24.8+ |
82
43
 
83
- The client may work with older versions too; however, this is best-effort support and is not guaranteed.
44
+ The client may work with older versions too; however, this is best-effort
45
+ support and is not guaranteed.
84
46
 
85
47
  ## Quick start
86
48
 
87
49
  ```ts
88
- import { createClient } from "@clickhouse/client"; // or '@clickhouse/client-web'
50
+ import { createClient } from "@clickhouse/client";
89
51
 
90
52
  const client = createClient({
91
53
  url: process.env.CLICKHOUSE_URL ?? "http://localhost:8123",
@@ -104,41 +66,24 @@ console.log(tables);
104
66
  await client.close();
105
67
  ```
106
68
 
107
- See more examples in the [examples directory](./examples).
69
+ See more examples in the
70
+ [examples directory](https://github.com/ClickHouse/clickhouse-js/tree/main/examples).
108
71
 
109
72
  ## Documentation
110
73
 
111
- See the [ClickHouse website](https://clickhouse.com/docs/integrations/javascript) for the full documentation.
112
-
113
- ## AI Agent Skills
114
-
115
- This repository contains agent skills for working with the client:
116
-
117
- - `clickhouse-js-node-troubleshooting` — troubleshooting playbook for the Node.js client.
118
-
119
- Install via CLI:
74
+ See the [ClickHouse website](https://clickhouse.com/docs/integrations/javascript)
75
+ for the full documentation.
120
76
 
121
- ```sh
122
- # per project
123
- npx skills add ClickHouse/clickhouse-js
124
- # globally
125
- npx skills add ClickHouse/clickhouse-js -g
126
- ```
127
-
128
- Or ask your agent to install it for you:
77
+ ## Changelog
129
78
 
130
- > install agent skills from ClickHouse/clickhouse-js
131
-
132
- ## Usage examples
133
-
134
- We have a wide range of [examples](./examples), aiming to cover various scenarios of client usage. The overview is available in the [examples README](https://github.com/ClickHouse/clickhouse-js/blob/main/examples/README.md#overview).
79
+ See [`CHANGELOG.md`](https://github.com/ClickHouse/clickhouse-js/blob/main/packages/client-node/CHANGELOG.md).
135
80
 
136
81
  ## Contact us
137
82
 
138
- If you have any questions or need help, feel free to reach out to us in the [Community Slack](https://clickhouse.com/slack) (`#clickhouse-js` channel) or via [GitHub issues](https://github.com/ClickHouse/clickhouse-js/issues).
139
-
140
- ## Contributing
83
+ If you have any questions or need help, feel free to reach out to us in the
84
+ [Community Slack](https://clickhouse.com/slack) (`#clickhouse-js` channel) or
85
+ via [GitHub issues](https://github.com/ClickHouse/clickhouse-js/issues).
141
86
 
142
- Check out our [contributing guide](./CONTRIBUTING.md).
87
+ ## License
143
88
 
144
- If you'd like to build a client for an alternative runtime (such as Bun or Cloudflare Workers) or an alternative protocol (such as the native ClickHouse protocol or gRPC over a proxy), see [Building specialized clients for alternative runtimes and protocols](./ALTERNATIVE_CLIENTS.md).
89
+ [Apache 2.0](https://github.com/ClickHouse/clickhouse-js/blob/main/LICENSE)
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export { type BaseClickHouseClientConfigOptions, type BaseQueryParams, type Quer
13
13
  * applied to them in `./common/index` are NOT propagated to consumers of this package.
14
14
  * Importing these values from `@clickhouse/client` is the recommended, non-deprecated path.
15
15
  */
16
- import { ClickHouseError as ClickHouseError_, parseError as parseError_, ClickHouseLogLevel as ClickHouseLogLevel_, SettingsMap as SettingsMap_, parseColumnType as parseColumnType_, isProgressRow as isProgressRow_, isRow as isRow_, isException as isException_, TupleParam as TupleParam_ } from "./common/index";
16
+ import { ClickHouseError as ClickHouseError_, parseError as parseError_, ClickHouseLogLevel as ClickHouseLogLevel_, SettingsMap as SettingsMap_, parseColumnType as parseColumnType_, isProgressRow as isProgressRow_, isRow as isRow_, isException as isException_, TupleParam as TupleParam_, extractErrorAtTheEndOfChunk as extractErrorAtTheEndOfChunk_ } from "./common/index";
17
17
  export declare const ClickHouseError: typeof ClickHouseError_;
18
18
  export type ClickHouseError = ClickHouseError_;
19
19
  export declare const parseError: typeof parseError_;
@@ -70,3 +70,5 @@ export declare const ClickHouseSpanKind: {
70
70
  readonly CONSUMER: 4;
71
71
  };
72
72
  export declare const defaultJSONHandling: import("./common/index").JSONHandling;
73
+ export declare const EXCEPTION_TAG_HEADER_NAME = "x-clickhouse-exception-tag";
74
+ export declare const extractErrorAtTheEndOfChunk: typeof extractErrorAtTheEndOfChunk_;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defaultJSONHandling = exports.ClickHouseSpanKind = exports.ClickHouseSpanStatusCode = exports.ClickHouseSpanNames = exports.TupleParam = exports.isException = exports.isRow = exports.isProgressRow = exports.SimpleColumnTypes = exports.parseColumnType = exports.RecordsJSONFormats = exports.SingleDocumentJSONFormats = exports.StreamableJSONFormats = exports.StreamableFormats = exports.SupportedRawFormats = exports.SupportedJSONFormats = exports.SettingsMap = exports.ClickHouseLogLevel = exports.parseError = exports.ClickHouseError = exports.drainStream = exports.ResultSet = exports.createClient = exports.ClickHouseClient = void 0;
3
+ exports.extractErrorAtTheEndOfChunk = exports.EXCEPTION_TAG_HEADER_NAME = exports.defaultJSONHandling = exports.ClickHouseSpanKind = exports.ClickHouseSpanStatusCode = exports.ClickHouseSpanNames = exports.TupleParam = exports.isException = exports.isRow = exports.isProgressRow = exports.SimpleColumnTypes = exports.parseColumnType = exports.RecordsJSONFormats = exports.SingleDocumentJSONFormats = exports.StreamableJSONFormats = exports.StreamableFormats = exports.SupportedRawFormats = exports.SupportedJSONFormats = exports.SettingsMap = exports.ClickHouseLogLevel = exports.parseError = exports.ClickHouseError = exports.drainStream = exports.ResultSet = exports.createClient = exports.ClickHouseClient = void 0;
4
4
  var client_1 = require("./client");
5
5
  Object.defineProperty(exports, "ClickHouseClient", { enumerable: true, get: function () { return client_1.NodeClickHouseClient; } });
6
6
  var client_2 = require("./client");
@@ -40,4 +40,6 @@ exports.ClickHouseSpanNames = index_1.ClickHouseSpanNames;
40
40
  exports.ClickHouseSpanStatusCode = index_1.ClickHouseSpanStatusCode;
41
41
  exports.ClickHouseSpanKind = index_1.ClickHouseSpanKind;
42
42
  exports.defaultJSONHandling = index_1.defaultJSONHandling;
43
+ exports.EXCEPTION_TAG_HEADER_NAME = index_1.EXCEPTION_TAG_HEADER_NAME;
44
+ exports.extractErrorAtTheEndOfChunk = index_1.extractErrorAtTheEndOfChunk;
43
45
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAGkB;AAFhB,0GAAA,oBAAoB,OAAoB;AAG1C,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AAErB,2CAA8D;AAArD,uGAAA,SAAS,OAAA;AAClB,8CAAkD;AAAzC,qGAAA,WAAW,OAAA;AA2DpB;;;;;;;GAOG;AACH,0CAqBwB;AAEX,QAAA,eAAe,GAAG,uBAAgB,CAAC;AAEnC,QAAA,UAAU,GAAG,kBAAW,CAAC;AACzB,QAAA,kBAAkB,GAAG,0BAAmB,CAAC;AAEzC,QAAA,WAAW,GAAG,mBAAY,CAAC;AAE3B,QAAA,oBAAoB,GAAG,4BAAqB,CAAC;AAC7C,QAAA,mBAAmB,GAAG,2BAAoB,CAAC;AAC3C,QAAA,iBAAiB,GAAG,yBAAkB,CAAC;AACvC,QAAA,qBAAqB,GAAG,6BAAsB,CAAC;AAC/C,QAAA,yBAAyB,GAAG,iCAA0B,CAAC;AACvD,QAAA,kBAAkB,GAAG,0BAAmB,CAAC;AACtD,4JAA4J;AAC/I,QAAA,eAAe,GAAG,uBAAgB,CAAC;AAChD,4JAA4J;AAC/I,QAAA,iBAAiB,GAAG,yBAAkB,CAAC;AACvC,QAAA,aAAa,GAAG,qBAAc,CAAC;AAC/B,QAAA,KAAK,GAAG,aAAM,CAAC;AACf,QAAA,WAAW,GAAG,mBAAY,CAAC;AAC3B,QAAA,UAAU,GAAG,kBAAW,CAAC;AAEzB,QAAA,mBAAmB,GAAG,2BAAoB,CAAC;AAC3C,QAAA,wBAAwB,GAAG,gCAAyB,CAAC;AACrD,QAAA,kBAAkB,GAAG,0BAAmB,CAAC;AACzC,QAAA,mBAAmB,GAAG,2BAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAGkB;AAFhB,0GAAA,oBAAoB,OAAoB;AAG1C,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AAErB,2CAA8D;AAArD,uGAAA,SAAS,OAAA;AAClB,8CAAkD;AAAzC,qGAAA,WAAW,OAAA;AA2DpB;;;;;;;GAOG;AACH,0CAuBwB;AAEX,QAAA,eAAe,GAAG,uBAAgB,CAAC;AAEnC,QAAA,UAAU,GAAG,kBAAW,CAAC;AACzB,QAAA,kBAAkB,GAAG,0BAAmB,CAAC;AAEzC,QAAA,WAAW,GAAG,mBAAY,CAAC;AAE3B,QAAA,oBAAoB,GAAG,4BAAqB,CAAC;AAC7C,QAAA,mBAAmB,GAAG,2BAAoB,CAAC;AAC3C,QAAA,iBAAiB,GAAG,yBAAkB,CAAC;AACvC,QAAA,qBAAqB,GAAG,6BAAsB,CAAC;AAC/C,QAAA,yBAAyB,GAAG,iCAA0B,CAAC;AACvD,QAAA,kBAAkB,GAAG,0BAAmB,CAAC;AACtD,4JAA4J;AAC/I,QAAA,eAAe,GAAG,uBAAgB,CAAC;AAChD,4JAA4J;AAC/I,QAAA,iBAAiB,GAAG,yBAAkB,CAAC;AACvC,QAAA,aAAa,GAAG,qBAAc,CAAC;AAC/B,QAAA,KAAK,GAAG,aAAM,CAAC;AACf,QAAA,WAAW,GAAG,mBAAY,CAAC;AAC3B,QAAA,UAAU,GAAG,kBAAW,CAAC;AAEzB,QAAA,mBAAmB,GAAG,2BAAoB,CAAC;AAC3C,QAAA,wBAAwB,GAAG,gCAAyB,CAAC;AACrD,QAAA,kBAAkB,GAAG,0BAAmB,CAAC;AACzC,QAAA,mBAAmB,GAAG,2BAAoB,CAAC;AAC3C,QAAA,yBAAyB,GAAG,iCAA0B,CAAC;AACvD,QAAA,2BAA2B,GAAG,mCAA4B,CAAC"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "1.23.0-head.287977a.1";
1
+ declare const _default: "1.23.0-head.71b2e8a.1";
2
2
  export default _default;
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = "1.23.0-head.287977a.1";
3
+ exports.default = "1.23.0-head.71b2e8a.1";
4
4
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@clickhouse/client",
3
3
  "description": "Official JS client for ClickHouse DB - Node.js implementation",
4
4
  "homepage": "https://clickhouse.com",
5
- "version": "1.23.0-head.287977a.1",
5
+ "version": "1.23.0-head.71b2e8a.1",
6
6
  "license": "Apache-2.0",
7
7
  "keywords": [
8
8
  "clickhouse",
@@ -15,13 +15,14 @@
15
15
  },
16
16
  "private": false,
17
17
  "engines": {
18
- "node": ">=16"
18
+ "node": ">=20"
19
19
  },
20
20
  "main": "dist/index.js",
21
21
  "types": "dist/index.d.ts",
22
22
  "files": [
23
23
  "dist",
24
- "skills"
24
+ "skills",
25
+ "CHANGELOG.md"
25
26
  ],
26
27
  "agents": {
27
28
  "skills": [
@@ -34,18 +35,28 @@
34
35
  "path": "./skills/clickhouse-js-node-troubleshooting"
35
36
  },
36
37
  {
37
- "name": "clickhouse-js-node-rowbinary-parser",
38
- "path": "./skills/clickhouse-js-node-rowbinary-parser"
38
+ "name": "clickhouse-js-node-rowbinary",
39
+ "path": "./skills/clickhouse-js-node-rowbinary"
39
40
  }
40
41
  ]
41
42
  },
42
43
  "scripts": {
43
44
  "pack": "npm pack",
44
- "prepack": "rm -rf skills && cp ../../README.md ../../LICENSE . && cp -r ../../skills . && RBP=skills/clickhouse-js-node-rowbinary-parser && rm -rf $RBP/tests $RBP/node_modules $RBP/dist $RBP/package.json $RBP/package-lock.json $RBP/tsconfig.json $RBP/tsconfig.build.json $RBP/vitest.config.ts $RBP/.gitignore $RBP/LICENSE $RBP/eval_result*.md",
45
+ "prepack": "rm -rf skills && cp ../../LICENSE . && cp -r ../../skills . && RBP=skills/clickhouse-js-node-rowbinary && rm -rf $RBP/tests $RBP/node_modules $RBP/dist $RBP/package.json $RBP/package-lock.json $RBP/tsconfig.json $RBP/tsconfig.build.json $RBP/vitest.config.ts $RBP/.gitignore $RBP/LICENSE $RBP/eval_result*.md",
45
46
  "typecheck": "tsc --noEmit",
46
47
  "lint": "eslint --max-warnings=0 .",
47
48
  "lint:fix": "eslint . --fix",
48
- "build": "rm -rf dist; tsc"
49
+ "build": "rm -rf dist; tsc",
50
+ "test:unit": "CLICKHOUSE_TEST_SKIP_INIT=1 TEST_MODE=unit vitest",
51
+ "test:unit:bun": "CLICKHOUSE_TEST_SKIP_INIT=1 TEST_MODE=unit bun --bun vitest",
52
+ "test:integration": "TEST_MODE=integration vitest",
53
+ "test:integration:tls": "TEST_MODE=tls vitest",
54
+ "test:integration:dist": "npm --prefix ../.. run build && TEST_TARGET=dist TEST_MODE=integration vitest",
55
+ "test:integration:local_cluster": "CLICKHOUSE_TEST_ENVIRONMENT=local_cluster TEST_MODE=integration vitest",
56
+ "test:integration:cloud": "CLICKHOUSE_TEST_ENVIRONMENT=cloud TEST_MODE=integration vitest",
57
+ "test:oss-dependents": "TEST_MODE=oss-dependents vitest",
58
+ "test:all": "TEST_MODE=all vitest",
59
+ "test:coverage": "VITEST_COVERAGE=true TEST_MODE=all vitest"
49
60
  },
50
61
  "dependencies": {},
51
62
  "devDependencies": {
@@ -0,0 +1,8 @@
1
+ # Recommendations for AI agents — `skills/`
2
+
3
+ Guidance for the shipped agent skills. See the [repo-root `AGENTS.md`](../AGENTS.md) for cross-cutting guidance. The `@clickhouse/rowbinary` skill has its own [`clickhouse-js-node-rowbinary/AGENTS.md`](clickhouse-js-node-rowbinary/AGENTS.md).
4
+
5
+ - Each shipped skill must also be listed in the `agents.skills` array of
6
+ [`packages/client-node/package.json`](../packages/client-node/package.json) so downstream tooling can
7
+ discover it. The [`Skills E2E`](../.github/workflows/e2e-skills.yml) workflow
8
+ (`tests/e2e/skills/check.js`) asserts that the packaged tarball contains the declared skills.
@@ -0,0 +1,44 @@
1
+ # Recommendations for AI agents — `@clickhouse/rowbinary`
2
+
3
+ Guidance for the [`clickhouse-js-node-rowbinary`](.) package (the RowBinary codec library and agent skill). See the [repo-root `AGENTS.md`](../../AGENTS.md) for cross-cutting guidance.
4
+
5
+ This package has a symmetric reader/writer codebase.
6
+
7
+ ## Tests
8
+
9
+ The tests follow a few conventions worth preserving:
10
+
11
+ - **Reader and writer tests are separate files.** Readers are tested in `tests/*.test.ts`; writers in
12
+ `tests/*.write.test.ts`. Keep the two independent: a writer test must **never** decode its bytes back
13
+ through a reader (and vice versa), so a bug on one side cannot mask a bug on the other. Writer tests
14
+ assert the encoded bytes against **live ClickHouse output** as the source of truth.
15
+ - **Each case is an isolated `it()` with a fully-inline body.** Write the assertion out per case, e.g.
16
+ `expect(encode(writer, value)).toEqual(await query("SELECT … FORMAT RowBinary"))`. Do **not** hide the
17
+ assertion behind a thunk-factory helper (`it("name", expectFoo(...))`), and do **not** wrap the query
18
+ in a per-file helper — embed the literal SQL inline, including any `SETTINGS` clause, so the full
19
+ query is visible in the test. The only shared helpers are the generic `query()` (`tests/clickhouse.ts`,
20
+ runs SQL → bytes) and `encode()` (`tests/encode.ts`, value → bytes). Repeating SQL across cases is
21
+ fine; reviewability beats DRY here. See [`tests/Integers.write.test.ts`](tests/Integers.write.test.ts)
22
+ as the canonical example.
23
+
24
+ ## No defensive validation in readers/writers
25
+
26
+ These are hot-path codecs. **Do not add runtime validation of input values** (`isFinite`,
27
+ range/`NaN` checks, type guards, etc.) to the `readX`/`writeX` functions. The data at this level is
28
+ expected to be correct, and an invalid value is a programming error — document the precondition in the
29
+ JSDoc instead (see `writeUVarint` and the `writeDate*`/`writeDateTime` writers as the canonical
30
+ examples). A `Math.round`-style transform that silently shifts a _valid_ value to the wrong encoding is
31
+ a correctness bug and must be fixed; rejecting an _invalid_ value is not our job here.
32
+
33
+ Two narrow exceptions where a check **is** warranted:
34
+
35
+ 1. **It keeps the protocol in sync.** A check belongs in only when skipping it would desync the wire
36
+ stream — e.g. `writeIPv6` requires exactly 16 bytes because a wrong length shifts every subsequent
37
+ field, and `parseIPv6` rejects malformed groups because it can't otherwise produce 16 well-defined
38
+ bytes. These guard the _framing_, not the user's data semantics.
39
+ 2. **The cost is genuinely zero or it can't reach the server.** Pure parse-time helpers (string →
40
+ bytes, before anything is on the wire) may validate, since there's no hot loop and no server to fall
41
+ back on.
42
+
43
+ Otherwise, prefer letting the ClickHouse server reject bad bytes server-side over guarding client-side:
44
+ it already validates, and duplicating that on the encode path costs throughput for no real safety.
@@ -0,0 +1,49 @@
1
+ # Changelog — `@clickhouse/rowbinary`
2
+
3
+ > This file tracks the standalone `@clickhouse/rowbinary` package (the RowBinary
4
+ > parser library and agent skill). Entries relevant to it (through
5
+ > `@clickhouse/client` 1.23.0) were previously recorded in the now-frozen
6
+ > repository-wide [`CHANGELOG.md`](../../CHANGELOG.md).
7
+
8
+ # 0.2.0
9
+
10
+ ## New features
11
+
12
+ - Added the RowBinary **writer** — the encode mirror of the reader: type-specific `writeX(sink, value)` building blocks and combinators that compose with no per-element closures, exported from `@clickhouse/rowbinary/writer` (or the per-type modules). ([#911])
13
+
14
+ `writeRows(writeRow)` drives an `Iterable<T>` of rows into a plain `RowBinary` payload. Note its shape: it is a **streaming generator**, not a one-shot `Writer<readonly T[]>`. It writes into a fixed-size buffer (`bufferSize`, default 64 KiB), yields each batch of whole rows when the buffer fills — rewinding so a half-written row never leaks — and starts a fresh buffer for the rest, so a result larger than the buffer (or an unbounded row source) streams out chunk by chunk. An oversized row grows the buffer (doubling) rather than failing, and per-buffer fill is published on the `@clickhouse/rowbinary:writeRows.flush` `node:diagnostics_channel` for buffer-utilization metrics. ([#915])
15
+
16
+ ```ts
17
+ import {
18
+ writeRows,
19
+ writeTupleNamed,
20
+ writeUInt64,
21
+ writeString,
22
+ } from "@clickhouse/rowbinary/writer";
23
+
24
+ const writeRow = writeTupleNamed({ id: writeUInt64, name: writeString });
25
+ for (const chunk of writeRows(writeRow)(rows, 64 * 1024)) send(chunk);
26
+ ```
27
+
28
+ Writer edge-case hardening: `writeDate`/`writeDate32`/`writeDateTime` floor to the calendar day / whole second instead of rounding (so a non-midnight `Date` or sub-second `DateTime` no longer rounds up); `parseIPv6` rejects malformed hex groups instead of silently encoding `0`; and `writeGeometry` validates the discriminant before writing its byte, so an out-of-range value can't leave a partial payload. ([#916])
29
+
30
+ [#911]: https://github.com/ClickHouse/clickhouse-js/pull/911
31
+ [#915]: https://github.com/ClickHouse/clickhouse-js/pull/915
32
+ [#916]: https://github.com/ClickHouse/clickhouse-js/pull/916
33
+
34
+ # 0.1.2
35
+
36
+ ## Improvements
37
+
38
+ - Bumped the bundled `@clickhouse/datatype-parser` dependency to `0.1.2`. ([#895])
39
+ - Patch release. ([#903])
40
+
41
+ # 0.1.1
42
+
43
+ ## New features
44
+
45
+ - Initial release of `@clickhouse/rowbinary`: a RowBinary reader library (and the companion agent skill) shipping type-specific, monomorphizable building blocks for decoding `RowBinary` / `RowBinaryWithNames` / `RowBinaryWithNamesAndTypes` streams (full-buffer and chunked), plus a skill that guides an agent to generate bespoke high-performance parsers from a query's column types. The same library is also bundled into `@clickhouse/client` (registered in `agents.skills`). Requires Node.js `>=20`. A matching RowBinary writer is planned. ([#864])
46
+
47
+ [#864]: https://github.com/ClickHouse/clickhouse-js/pull/864
48
+ [#895]: https://github.com/ClickHouse/clickhouse-js/pull/895
49
+ [#903]: https://github.com/ClickHouse/clickhouse-js/pull/903
@@ -1,10 +1,10 @@
1
- # ClickHouse Node.js RowBinary Parser Generator
1
+ # ClickHouse Node.js RowBinary Codec Generator
2
2
 
3
- **If JS had a -O3 compiler flag, this skill would be it.** (for RowBinary parsing)
3
+ **If JS had a -O3 compiler flag, this skill would be it.** (for RowBinary read & write)
4
4
 
5
- A skill and a library that lets a coding agent generate bespoke RowBinary parsers on the first pass from the column type definitions of a ClickHouse response. The [spirit](#the-spirit) behind the approach.
5
+ A skill and a library that lets a coding agent generate bespoke RowBinary codecs on the first pass from the column type definitions of a ClickHouse response. The [spirit](#the-spirit) behind the approach.
6
6
 
7
- **Reader only** for now. Today this covers reading (decoding) RowBinary streams. A matching RowBinary writer (encoding) is planned.
7
+ **Reads and writes.** Both directions are covered: readers (decode bytes → values) and writers (encode values bytes), split under `src/readers/` and `src/writers/`. The reader path is the more mature one — the writers mirror it type-for-type, with a few decode-only paths (`Dynamic`, `JSON`, the runtime header/compile path, and the columnar typed-array path) not yet mirrored.
8
8
 
9
9
  ## Status
10
10
 
@@ -12,7 +12,7 @@ A skill and a library that lets a coding agent generate bespoke RowBinary parser
12
12
  - ✅ Opus 4.8: 71% -> 94.7% pass rate
13
13
  - ✅ Haiku 4.5: 52% -> 86.0% pass rate
14
14
  - ✅ Composer 2.5 Fast: 3x parser performance
15
- - ✅ 469/469 tests
15
+ - ✅ 724/724 tests (readers + writers)
16
16
  - ✅ type-checked
17
17
  - ✅ benchmarked
18
18
 
@@ -35,7 +35,7 @@ const readOrderRow: Reader<OrderRow> = (s) => ({
35
35
  id: readUInt8(s),
36
36
  uid: formatUUID(readUUID(s)),
37
37
  price: readDecimal64(2)(s),
38
- status: readEnum8(s),
38
+ status: readInt8(s), // raw enum int; `readEnum8(map)` resolves it to the name
39
39
  });
40
40
  ```
41
41
 
@@ -70,14 +70,74 @@ npx skills-npm setup
70
70
  As a skill only:
71
71
 
72
72
  ```bash
73
- npx skills add ClickHouse/clickhouse-js/skills/clickhouse-js-node-rowbinary-parser
73
+ npx skills add ClickHouse/clickhouse-js/skills/clickhouse-js-node-rowbinary
74
74
  ```
75
75
 
76
76
  ```console
77
- > Hey, Claude, tell me what the rowbinary parser skill can do for me.
78
- > A lot! It generates custom, high-performance RowBinary parsers
79
- > Super, generate a parser for the queries in app/src/model.ts.
80
- < Reading skill clickhouse-js-node-rowbinary-parser
77
+ > Hey, Claude, tell me what the rowbinary skill can do for me.
78
+ > A lot! It generates custom, high-performance RowBinary readers and writers
79
+ > Super, generate a reader for the queries in app/src/model.ts.
80
+ < Reading skill clickhouse-js-node-rowbinary…
81
+ ```
82
+
83
+ ## Using it with the ClickHouse JS client
84
+
85
+ This library only **decodes** the bytes — it doesn't open connections. Pair it
86
+ with the official client to fetch a `RowBinary` response and feed the byte chunks
87
+ into `streamRowBatches(chunks, readRow)`.
88
+
89
+ `RowBinary` isn't one of the formats the client decodes itself, so don't use
90
+ `client.query({ format: ... })` for it. Instead use `client.exec({ query })` with
91
+ the `FORMAT RowBinary` clause written into the SQL yourself — `exec` hands back the
92
+ **raw, undecoded byte stream** of the response, which is exactly what this library
93
+ consumes. (Use plain `RowBinary`, not `RowBinaryWithNamesAndTypes`, unless your
94
+ reader also skips the leading names/types header.)
95
+
96
+ The row reader below is the `orders` example from [EXAMPLES.md](EXAMPLES.md); swap
97
+ in the reader the skill generates for your own columns.
98
+
99
+ ```ts
100
+ import {
101
+ type Reader,
102
+ readUInt8,
103
+ readInt8,
104
+ readUUID,
105
+ formatUUID,
106
+ readDecimal64,
107
+ type DecimalValue,
108
+ streamRowBatches,
109
+ } from "@clickhouse/rowbinary";
110
+ import { createClient } from "@clickhouse/client";
111
+
112
+ type OrderRow = {
113
+ id: number;
114
+ uid: string;
115
+ price: DecimalValue;
116
+ status: number;
117
+ };
118
+
119
+ const readOrderRow: Reader<OrderRow> = (s) => ({
120
+ id: readUInt8(s),
121
+ uid: formatUUID(readUUID(s)),
122
+ price: readDecimal64(2)(s),
123
+ status: readInt8(s), // raw enum int; `readEnum8(map)` resolves it to the name
124
+ });
125
+
126
+ // `exec` resolves to a Node `Stream.Readable`. It is already an
127
+ // `AsyncIterable<Uint8Array>` (chunks are `Buffer`/`Uint8Array`, which
128
+ // `streamRowBatches` normalizes), so pass `stream` straight in:
129
+
130
+ const client = createClient();
131
+
132
+ const { stream } = await client.exec({
133
+ query: "SELECT id, uid, price, status FROM orders FORMAT RowBinary",
134
+ });
135
+
136
+ for await (const rows of streamRowBatches(stream, readOrderRow)) {
137
+ for (const row of rows) console.log(row); // { id, uid, price: [unscaled, scale], status }
138
+ }
139
+
140
+ await client.close();
81
141
  ```
82
142
 
83
143
  ## Why it's worth it
@@ -208,18 +268,22 @@ Measure, don't assume.
208
268
 
209
269
  ## Scope
210
270
 
211
- - **In scope:** `RowBinary`, `RowBinaryWithNames`, and
271
+ - **In scope (reading):** `RowBinary`, `RowBinaryWithNames`, and
212
272
  `RowBinaryWithNamesAndTypes` decoding for Node.js — full-buffer and streaming
213
273
  (chunked) via `advance()`/`NeedMoreData`, `readRows()`, and the async
214
274
  `streamRowBatches()` (with a built-in small-chunk warning and the optional
215
275
  `coalesceChunks()` debounce filter).
216
- - **Planned:** RowBinary **writing / encoding** (the inverse of everything above)
276
+ - **In scope (writing):** the inverse encode path — a `writeX` mirroring every
277
+ `readX`, appending bytes to a `Sink`, plus `writeRows()`. Imported from
278
+ `@clickhouse/rowbinary/writer`. A handful of decode-only paths are not yet
279
+ mirrored: `Dynamic`, `JSON`, the runtime header/compile path, and the columnar
280
+ typed-array path.
217
281
  - **Out of scope (for now):** browsers and Edge runtimes, non-RowBinary formats
218
282
  (JSON / CSV / TSV / Parquet), and big-endian hosts.
219
283
 
220
284
  ## The spirit
221
285
 
222
- A RowBinary parser generator is a narrow thing. But it's built as an instance of
286
+ A RowBinary codec generator is a narrow thing. But it's built as an instance of
223
287
  a broader bet about what libraries become once a capable LLM is part of the
224
288
  toolchain. Three shifts, each already visible in this repo:
225
289
 
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: clickhouse-js-node-rowbinary
3
+ description: >
4
+ Generate TypeScript/JavaScript code that reads/decodes AND writes/encodes
5
+ ClickHouse RowBinary streams for the ClickHouse HTTP server.
6
+ Use this skill whenever a user wants to parse or produce `RowBinary`,
7
+ `RowBinaryWithNames`, or `RowBinaryWithNamesAndTypes`.
8
+ Node.js only, doesn't cover browsers.
9
+ ---
10
+
11
+ # ClickHouse JS RowBinary Codec Generator for Node.js
12
+
13
+ This skill generates both directions of the wire format: **readers** (decode
14
+ bytes → values) and **writers** (encode values → bytes, the mirror). A given
15
+ task normally needs only one side. This file is the shared entry point — the
16
+ format gate plus the principles common to both directions; the per-direction
17
+ decisions, guidance, and the per-type reference tables live in two sibling files.
18
+
19
+ **Pick your side — read only the one you need:**
20
+
21
+ - **Decoding a `RowBinary*` response** from ClickHouse into JS values →
22
+ **[reader.md](reader.md)**. Streaming vs whole-buffer, row-objects vs columnar,
23
+ fixed vs runtime schema, and the per-type reader reference.
24
+ - **Encoding JS values into a `RowBinary` payload** to send to ClickHouse →
25
+ **[writer.md](writer.md)**. The `Sink`/`writeX` building blocks, `writeRows`
26
+ streaming, and the per-type writer reference.
27
+
28
+ The per-type code is real, split by direction under `src/readers/` and
29
+ `src/writers/`.
30
+
31
+ ## First: is RowBinary even the right format?
32
+
33
+ RowBinary exists for throughput, but it is **not automatically the fastest
34
+ path** — match the format to the shape of the data before committing to a
35
+ bespoke parser.
36
+
37
+ **Prefer a `JSON*` format (e.g. `JSONEachRow`) when** the result is mostly
38
+ strings / JSON-like values that you consume wholesale — randomly accessing
39
+ essentially every field, running string/regexp methods on them, treating values
40
+ as text. V8's native `JSON.parse` is heavily optimized C++ and builds JS strings
41
+ and objects faster than a JS-level RowBinary decoder can; pair it with HTTP
42
+ response compression (`gzip` / `zstd`, which crushes JSON's repetitive keys) and
43
+ the wire cost shrinks too.
44
+
45
+ **RowBinary clearly wins when** the result is dominated by:
46
+
47
+ - **Wide numerics** — `Int128`/`Int256`/`UInt128`/`UInt256`,
48
+ `Decimal128`/`Decimal256`.
49
+ - **Binary / fixed-width blobs** — `IPv4`, `IPv6`, `UUID`, `FixedString`.
50
+ - **High-volume fixed-width numeric columns** generally, where each value is a
51
+ single `DataView` read.
52
+
53
+ **Prefer the `Native` format when** columnar load and client-side analytics are
54
+ the main goal (fold/scan/filter columns, feed typed arrays to a Worker or WASM).
55
+ `Native` is column-major, so it loads straight into one typed array per column
56
+ with no transpose.
57
+
58
+ For help choosing and consuming a `JSON*` format (or CSV / TSV) instead, use the
59
+ **`clickhouse-js-node-coding`** skill.
60
+
61
+ ## Core guidance (both directions)
62
+
63
+ These principles apply whether you are generating a reader or a writer; the
64
+ side-specific operational guidance is in [reader.md](reader.md) /
65
+ [writer.md](writer.md).
66
+
67
+ - **Little-endian only.** RowBinary is little-endian; target x86/ARM. Read and
68
+ write every multi-byte number with `DataView` accessors passing a **literal**
69
+ `true` for the `littleEndian` flag.
70
+
71
+ - **Correct first, then optimize.** First emit a correct codec built from the
72
+ plain per-type API. Only after it's correct (and tested) specialize it. Don't
73
+ bake performance assumptions in before correctness.
74
+
75
+ - **Monomorphize generic/composite types.** Emit specialized, inlined code per
76
+ type combination instead of passing functions as arguments where the type is
77
+ known ahead of time.
78
+
79
+ - **Inline the leaf ops.** The per-type `readX`/`writeX` functions are the
80
+ correct, composable reference; the generated codec should INLINE their bodies,
81
+ not call them, so the row loop is straight-line with no per-field indirection
82
+ (and so the fixed-width coalescing can fold the offset arithmetic together).
83
+
84
+ - **Annotate the type per column.** Inlining erases the type structure, so put a
85
+ short comment above each column's encode/decode block naming the ClickHouse
86
+ type it handles.
87
+
88
+ - **Shared scratch is not reentrant.** Some hot methods reuse a module-level
89
+ scratch buffer as a write-then-read pair — correct only because the access is
90
+ fully synchronous. An `async`/`yield` boundary between populating and reading
91
+ it corrupts the value.
92
+
93
+ - **TypeScript by default.** Generate TypeScript code and helpers unless the user
94
+ explicitly asks for plain JavaScript.
95
+
96
+ ## Worked examples
97
+
98
+ Six end-to-end examples with real speedup are catalogued in [EXAMPLES.md](EXAMPLES.md).
99
+
100
+ ## Out of scope
101
+
102
+ - **JSON / CSV / TSV / Parquet parsing** → use `clickhouse-js-node-coding`.
103
+ - **Connection errors, hangs, type mismatches** → use
104
+ `clickhouse-js-node-troubleshooting`.
105
+ - **Browser / Web Worker / Edge** → `@clickhouse/client-web`.
106
+
107
+ ## Still Stuck?
108
+
109
+ - [ClickHouse RowBinary format](https://clickhouse.com/docs/interfaces/formats#rowbinary)
110
+ - [ClickHouse data types](https://clickhouse.com/docs/sql-reference/data-types)
111
+ - [ClickHouse JS client docs](https://clickhouse.com/docs/integrations/javascript)