kafka-console 1.1.16 → 1.2.3

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/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2021 Ivan Zakharchanka (https://github.com/3axap4eHko)
4
+
5
+ Permission is hereby granted, free of charge,
6
+ to any person obtaining a copy of this software and
7
+ associated documentation files (the "Software"), to
8
+ deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify,
10
+ merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom
12
+ the Software is furnished to do so,
13
+ subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice
16
+ shall be included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -5,16 +5,81 @@ Command line tool to sufficiently and easy work with Kafka
5
5
  [![NPM version][npm-image]][npm-url]
6
6
  [![Downloads][downloads-image]][npm-url]
7
7
 
8
-
9
- ## Installation
8
+ ## Table of Contents
9
+
10
+ - [Features](#features)
11
+ - [Installing](#installing)
12
+ - [Examples](#examples)
13
+ - [Consumer](#consumer)
14
+ - [Producer](#producer)
15
+ - [Formatters](#formatters)
16
+ - [Environment](#environment)
17
+ - [License](#license)
18
+
19
+ ## Features
20
+
21
+ - Producer
22
+ - Consumer groups with seek and timeout
23
+ - Built-in message encoders/decoders with types: json, js, raw
24
+ - Custom message encoders/decoders as a js module
25
+ - Message headers
26
+ - GZIP compression
27
+ - Plain, SSL and SASL_SSL implementations
28
+ - Admin client
29
+ - TypeScript support
30
+
31
+ ## Installing
10
32
 
11
33
  ```sh
12
34
  npm install -g kafka-console
13
35
  ```
14
36
 
15
- ## Usage
37
+ ## Examples
38
+
39
+ ### Common options
40
+ ```
41
+ -b, --brokers <brokers> bootstrap server host (default: "localhost:9092")
42
+ -l, --log-level <logLevel> log level
43
+ -t, --timeout <timeout> set a timeout of operation (default: "0")
44
+ --ssl enable ssl (default: false)
45
+ --mechanism <mechanism> sasl mechanism
46
+ --username <username> sasl username
47
+ --password <password> sasl password
48
+ --auth-id <authId> sasl aws authorization identity
49
+ --access-key-id <accessKeyId> sasl aws access key id
50
+ --secret-access-key <secretAccessKey> sasl aws secret access key
51
+ --session-token <seccionToken> sasl aws session token
52
+ --oauth-bearer <oauthBearer> sasl oauth bearer token
53
+ -V, --version output the version number
54
+ -h, --help display help for command
55
+ ```
56
+
57
+ ### Commands
58
+ ```
59
+ consume [options] <topic> Consume kafka topic events
60
+ produce [options] <topic> Produce kafka topic events
61
+ metadata Displays kafka server metadata
62
+ list|ls [options] Lists kafka topics
63
+ config [options] Describes config for specific resource
64
+ create <topic> Creates kafka topic
65
+ delete <topic> Deletes kafka topic
66
+ help [command] display help for command
67
+ ```
68
+
69
+ ### Consumer
16
70
 
17
- ### Consumer usage
71
+ `kcli consume [options] <topic>`
72
+
73
+ #### Options
74
+ ```
75
+ -g, --group <group> consumer group name
76
+ -f, --format <format> message type decoding json, js, raw (default: "json")
77
+ -o, --output <filename> write output to specified filename
78
+ -a, --from-beginning read messages from the beginning (default: false)
79
+ -c, --count <count> a number of messages to read (default: null)
80
+ -s, --skip <skip> a number of messages to skip (default: 0)
81
+ -h, --help display help for command
82
+ ```
18
83
 
19
84
  General usage with authentication
20
85
  ```sh
@@ -31,7 +96,18 @@ Custom data formatter example
31
96
  kcli consume $KAFKA_TOPIC --format ./formatter/avro.js | jq
32
97
  ```
33
98
 
34
- ### Producer usage
99
+ ### Producer
100
+
101
+ `kcli produce [options] <topic>`
102
+
103
+ #### Options
104
+ ```
105
+ -f, --format <format> message format encoding json, js, raw (default: "json")
106
+ -i, --input <filename> input filename
107
+ -d, --delay <delay> delay in ms after event emitting (default: 0)
108
+ -h, --header <header> set a static header (default: [])
109
+ --help display help for command
110
+ ```
35
111
 
36
112
  General usage
37
113
  ```sh
@@ -70,7 +146,7 @@ export interface Encoder<T> {
70
146
  }
71
147
 
72
148
  export interface Decoder<T> {
73
- (value: string | Buffer): Promise<T> | T;
149
+ (value: Buffer): Promise<T> | T;
74
150
  }
75
151
 
76
152
  export interface Formatter<T> {
@@ -79,6 +155,19 @@ export interface Formatter<T> {
79
155
  }
80
156
  ```
81
157
 
158
+ ## Environment
159
+
160
+ - KAFKA_BROKERS
161
+ - KAFKA_TIMEOUT
162
+ - KAFKA_MECHANISM
163
+ - KAFKA_USERNAME
164
+ - KAFKA_PASSWORD
165
+ - KAFKA_AUTH_ID
166
+ - KAFKA_ACCESS_KEY_ID
167
+ - KAFKA_SECRET_ACCESS_KEY
168
+ - KAFKA_SESSION_TOKEN
169
+ - KAFKA_OAUTH_BEARER
170
+
82
171
  ## License
83
172
  License [The MIT License](http://opensource.org/licenses/MIT)
84
173
  Copyright (c) 2021 Ivan Zakharchanka
@@ -52,11 +52,17 @@ const formatters_1 = require("../utils/formatters");
52
52
  function consume(topic, opts, { parent }) {
53
53
  var e_1, _a;
54
54
  return __awaiter(this, void 0, void 0, function* () {
55
- const _b = Object.assign(Object.assign({}, parent.opts()), opts), { group, format, fromBeginning, filename, brokers, logLevel, ssl } = _b, rest = __rest(_b, ["group", "format", "fromBeginning", "filename", "brokers", "logLevel", "ssl"]);
56
- const sasl = (0, kafka_1.getSASL)(rest);
55
+ const _b = Object.assign(Object.assign({}, parent.opts()), opts), { group, format, fromBeginning, count, skip, filename, brokers, logLevel, timeout, ssl } = _b, saslOptions = __rest(_b, ["group", "format", "fromBeginning", "count", "skip", "filename", "brokers", "logLevel", "timeout", "ssl"]);
56
+ const sasl = (0, kafka_1.getSASL)(saslOptions);
57
57
  const client = (0, kafka_1.createClient)(brokers, ssl, sasl, logLevel);
58
58
  const output = filename ? Fs.createWriteStream(filename) : process.stdout;
59
- const consumer = yield (0, kafka_1.createConsumer)(client, group, topic, fromBeginning);
59
+ const consumer = yield (0, kafka_1.createConsumer)(client, group, topic, fromBeginning, { skip, count, timeout });
60
+ consumer.onDone((timeouted) => {
61
+ if (timeouted) {
62
+ console.log("TIMEOUT");
63
+ process.exit(1);
64
+ }
65
+ });
60
66
  const formatter = (0, formatters_1.getFormatter)(format);
61
67
  try {
62
68
  for (var consumer_1 = __asyncValues(consumer), consumer_1_1; consumer_1_1 = yield consumer_1.next(), !consumer_1_1.done;) {
package/build/index.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.collect = void 0;
6
+ exports.toInt = exports.collect = void 0;
7
7
  const commander_1 = require("commander");
8
8
  const kafka_1 = require("./utils/kafka");
9
9
  const consume_1 = __importDefault(require("./commands/consume"));
@@ -18,10 +18,15 @@ function collect(value, result) {
18
18
  return result.concat([value]);
19
19
  }
20
20
  exports.collect = collect;
21
+ function toInt(value, result) {
22
+ return parseInt(value, 10);
23
+ }
24
+ exports.toInt = toInt;
21
25
  const commander = new commander_1.Command();
22
26
  commander
23
27
  .option('-b, --brokers <brokers>', 'bootstrap server host', process.env.KAFKA_BROKERS || 'localhost:9092')
24
28
  .option('-l, --log-level <logLevel>', 'log level')
29
+ .option('-t, --timeout <timeout>', 'set a timeout of operation', toInt, process.env.KAFKA_TIMEOUT || '0')
25
30
  .option('--ssl', 'enable ssl', false)
26
31
  .option('--mechanism <mechanism>', 'sasl mechanism', process.env.KAFKA_MECHANISM)
27
32
  .option('--username <username>', 'sasl username', process.env.KAFKA_USERNAME)
@@ -35,16 +40,18 @@ commander
35
40
  commander
36
41
  .command('consume <topic>')
37
42
  .requiredOption('-g, --group <group>', 'consumer group name')
38
- .option('-f, --format <format>', 'message type decoding', 'json')
43
+ .option('-f, --format <format>', 'message type decoding json, js, raw', 'json')
39
44
  .option('-o, --output <filename>', 'write output to specified filename')
40
45
  .option('-a, --from-beginning', 'read messages from the beginning', false)
46
+ .option('-c, --count <count>', 'a number of messages to read', toInt, Infinity)
47
+ .option('-s, --skip <skip>', 'a number of messages to skip', toInt, 0)
41
48
  .description('Consume kafka topic events')
42
49
  .action(consume_1.default);
43
50
  commander
44
51
  .command('produce <topic>')
45
- .option('-f, --format <format>', 'message format encoding', 'json')
52
+ .option('-f, --format <format>', 'message format encoding json, js, raw', 'json')
46
53
  .option('-i, --input <filename>', 'input filename')
47
- .option('-d, --delay <delay>', 'delay in ms after event emitting', parseInt, 0)
54
+ .option('-d, --delay <delay>', 'delay in ms after event emitting', toInt, 0)
48
55
  .option('-h, --header <header>', 'set a static header', collect, [])
49
56
  .description('Produce kafka topic events')
50
57
  .action(produce_1.default);
@@ -3,23 +3,33 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getFormatter = exports.json = exports.js = void 0;
6
+ exports.getFormatter = exports.raw = exports.js = exports.json = void 0;
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const vm_1 = require("vm");
9
- exports.js = {
10
- encode: (value) => JSON.stringify(value, null, ' '),
11
- decode: (value) => (0, vm_1.runInNewContext)(value.toString(), { module: {} }),
12
- };
13
9
  exports.json = {
14
10
  encode: (value) => JSON.stringify(value),
15
11
  decode: (value) => JSON.parse(value.toString()),
16
12
  };
13
+ exports.js = {
14
+ encode: (value) => JSON.stringify(value, null, ' '),
15
+ decode: (value) => {
16
+ const m = { exports: {} };
17
+ (0, vm_1.runInNewContext)(value.toString(), { module: m });
18
+ return m.exports;
19
+ },
20
+ };
21
+ exports.raw = {
22
+ encode: (value) => value,
23
+ decode: (value) => value.toString('utf8'),
24
+ };
17
25
  function getFormatter(format) {
18
26
  switch (format) {
19
27
  case 'json':
20
28
  return exports.json;
21
29
  case 'js':
22
30
  return exports.js;
31
+ case 'raw':
32
+ return exports.raw;
23
33
  default:
24
34
  const modulePath = path_1.default.resolve(process.cwd(), format);
25
35
  return require(modulePath);
@@ -108,7 +108,7 @@ function createAdmin(client) {
108
108
  });
109
109
  }
110
110
  exports.createAdmin = createAdmin;
111
- function createConsumer(client, group, topic, fromBeginning = false) {
111
+ function createConsumer(client, group, topic, fromBeginning = false, poolOptions = {}) {
112
112
  return __awaiter(this, void 0, void 0, function* () {
113
113
  const consumerConfig = {
114
114
  groupId: group,
@@ -120,7 +120,7 @@ function createConsumer(client, group, topic, fromBeginning = false) {
120
120
  const consumer = client.consumer(consumerConfig);
121
121
  yield consumer.connect();
122
122
  yield consumer.subscribe(consumerOptions);
123
- const pool = new pool_1.default();
123
+ const pool = new pool_1.default([], poolOptions);
124
124
  pool.onDone(() => {
125
125
  consumer.disconnect();
126
126
  });
@@ -31,21 +31,36 @@ function createItem() {
31
31
  }
32
32
  exports.createItem = createItem;
33
33
  class CancelToken {
34
+ constructor(timeout) {
35
+ this.timeout = timeout;
36
+ }
34
37
  }
35
38
  exports.CancelToken = CancelToken;
36
39
  class Pool {
37
- constructor(values = []) {
40
+ constructor(values = [], { skip = 0, count = Infinity, timeout } = {}) {
38
41
  this.pool = [createItem()];
39
42
  this.doneEvent = (0, evnty_1.default)();
40
- values.forEach(value => this.push(value));
43
+ this.index = 0;
44
+ this.skip = skip;
45
+ this.count = count + skip;
46
+ if (typeof timeout === 'number') {
47
+ this.timerId = setTimeout(() => this.done(true), timeout);
48
+ }
49
+ values.forEach((value) => this.push(value));
41
50
  }
42
51
  push(value) {
43
- this.pool[this.pool.length - 1].resolve(value);
44
- this.pool.push(createItem());
52
+ if (this.index >= this.skip && this.index < this.count) {
53
+ this.pool[this.pool.length - 1].resolve(value);
54
+ this.pool.push(createItem());
55
+ }
56
+ this.index++;
57
+ if (this.index >= this.count) {
58
+ this.done();
59
+ }
45
60
  return this;
46
61
  }
47
- done() {
48
- this.pool[this.pool.length - 1].resolve(new CancelToken());
62
+ done(timeout = false) {
63
+ this.pool[this.pool.length - 1].resolve(new CancelToken(timeout));
49
64
  return this;
50
65
  }
51
66
  onDone(callback) {
@@ -80,7 +95,8 @@ class Pool {
80
95
  const value = yield this.pool[0].promise;
81
96
  this.pool.shift();
82
97
  if (value instanceof CancelToken) {
83
- this.doneEvent();
98
+ clearTimeout(this.timerId);
99
+ this.doneEvent(value.timeout);
84
100
  return {
85
101
  i: ++i,
86
102
  done: true,
@@ -94,6 +110,5 @@ class Pool {
94
110
  }),
95
111
  };
96
112
  }
97
- ;
98
113
  }
99
114
  exports.default = Pool;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kafka-console",
3
- "version": "1.1.16",
3
+ "version": "1.2.3",
4
4
  "description": "Kafka CLI tool",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -17,7 +17,14 @@
17
17
  "type": "git",
18
18
  "url": "git+https://github.com/3axap4eHko/kafka-console.git"
19
19
  },
20
- "keywords": [],
20
+ "keywords": [
21
+ "kafka",
22
+ "cli",
23
+ "commands",
24
+ "sasl",
25
+ "consumer",
26
+ "producer"
27
+ ],
21
28
  "author": "Ivan Zakharchanka",
22
29
  "license": "MIT",
23
30
  "bugs": {
@@ -26,19 +33,19 @@
26
33
  "homepage": "https://github.com/3axap4eHko/kafka-console#readme",
27
34
  "devDependencies": {
28
35
  "@types/commander": "^2.12.2",
29
- "@types/jest": "^27.0.2",
30
- "@types/js-yaml": "^4.0.4",
31
- "@types/node": "^16.11.6",
36
+ "@types/jest": "^27.0.3",
37
+ "@types/js-yaml": "^4.0.5",
38
+ "@types/node": "^17.0.2",
32
39
  "@types/winston": "^2.4.4",
33
40
  "dotenv": "^10.0.0",
34
- "jest": "^27.3.1",
35
- "ts-jest": "^27.0.7",
41
+ "jest": "^27.4.5",
42
+ "ts-jest": "^27.1.2",
36
43
  "ts-node": "^10.4.0",
37
- "typescript": "^4.4.4"
44
+ "typescript": "^4.5.4"
38
45
  },
39
46
  "dependencies": {
40
47
  "commander": "^8.3.0",
41
- "evnty": "^0.6.16",
48
+ "evnty": "^0.6.19",
42
49
  "kafkajs": "^1.15.0"
43
50
  }
44
51
  }