clickhouse-migrations 1.0.4 → 1.1.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 CHANGED
@@ -19,6 +19,8 @@ For migrations' content should be used correct SQL ClickHouse queries. Multiple
19
19
 
20
20
  If the database provided in the `--db` option (or in `CH_MIGRATIONS_DB`) doesn't exist, it will be created automatically.
21
21
 
22
+ For TLS/HTTPS connections, you can provide a custom CA certificate and optional client certificate/key via the `--ca-cert`, `--cert`, and `--key` options (or the `CH_MIGRATIONS_CA_CERT`, `CH_MIGRATIONS_CERT`, and `CH_MIGRATIONS_KEY` environment variables).
23
+
22
24
  ```
23
25
  Usage
24
26
  $ clickhouse-migrations migrate <options>
@@ -36,6 +38,9 @@ If the database provided in the `--db` option (or in `CH_MIGRATIONS_DB`) doesn't
36
38
  (default: 'ENGINE=Atomic')
37
39
  --timeout=<value> Client request timeout
38
40
  (milliseconds, default: 30000)
41
+ --ca-cert=<path> CA certificate file path
42
+ --cert=<path> Client certificate file path
43
+ --key=<path> Client key file path
39
44
 
40
45
  Environment variables
41
46
  Instead of options can be used environment variables.
@@ -48,6 +53,10 @@ If the database provided in the `--db` option (or in `CH_MIGRATIONS_DB`) doesn't
48
53
  CH_MIGRATIONS_DB_ENGINE (optional) DB engine (--db-engine)
49
54
  CH_MIGRATIONS_TIMEOUT (optional) Client request timeout
50
55
  (--timeout)
56
+ CH_MIGRATIONS_CA_CERT (optional) CA certificate file path
57
+ CH_MIGRATIONS_CERT (optional) Client certificate file path
58
+ CH_MIGRATIONS_KEY (optional) Client key file path
59
+
51
60
 
52
61
  CLI executions examples
53
62
  settings are passed as command-line options
@@ -66,6 +75,12 @@ If the database provided in the `--db` option (or in `CH_MIGRATIONS_DB`) doesn't
66
75
 
67
76
  settings provided partially through options and environment variables
68
77
  clickhouse-migrations migrate --timeout=60000
78
+
79
+ settings provided as options with TLS certificates
80
+ clickhouse-migrations migrate --host=https://localhost:8443
81
+ --user=default --password='' --db=analytics
82
+ --migrations-home=/app/clickhouse/migrations
83
+ --ca-cert=/app/certs/ca.pem --cert=/app/certs/client.crt --key=/app/certs/client.key
69
84
  ```
70
85
 
71
86
  Migration file example:
package/lib/migrate.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- declare const migration: (migrations_home: string, host: string, username: string, password: string, db_name: string, db_engine?: string, timeout?: string) => Promise<void>;
1
+ declare const migration: (migrations_home: string, host: string, username: string, password: string, db_name: string, db_engine?: string, timeout?: string, ca_cert?: string | undefined, cert?: string | undefined, key?: string | undefined) => Promise<void>;
2
2
  declare const migrate: () => void;
3
3
  export { migrate, migration };
package/lib/migrate.js CHANGED
@@ -63,7 +63,7 @@ var log = function (type, message, error) {
63
63
  console.error('\x1b[36m', "clickhouse-migrations :", '\x1b[31m', "Error: ".concat(message), error ? "\n\n ".concat(error) : '');
64
64
  }
65
65
  };
66
- var connect = function (url, username, password, db_name, timeout) {
66
+ var connect = function (url, username, password, db_name, timeout, ca_cert, cert, key) {
67
67
  var db_params = {
68
68
  url: url,
69
69
  username: username,
@@ -76,6 +76,26 @@ var connect = function (url, username, password, db_name, timeout) {
76
76
  if (timeout) {
77
77
  db_params.request_timeout = Number(timeout);
78
78
  }
79
+ if (ca_cert) {
80
+ try {
81
+ if (cert && key) {
82
+ db_params.tls = {
83
+ ca_cert: fs_1.default.readFileSync(ca_cert),
84
+ cert: fs_1.default.readFileSync(cert),
85
+ key: fs_1.default.readFileSync(key),
86
+ };
87
+ }
88
+ else {
89
+ db_params.tls = {
90
+ ca_cert: fs_1.default.readFileSync(ca_cert),
91
+ };
92
+ }
93
+ }
94
+ catch (e) {
95
+ log('error', 'Failed to read CA certificate file for TLS connection.', e instanceof Error ? e.message : String(e));
96
+ process.exit(1);
97
+ }
98
+ }
79
99
  return (0, client_1.createClient)(db_params);
80
100
  };
81
101
  var create_db = function (host_1, username_1, password_1, db_name_1) {
@@ -83,33 +103,46 @@ var create_db = function (host_1, username_1, password_1, db_name_1) {
83
103
  for (var _i = 4; _i < arguments.length; _i++) {
84
104
  args_1[_i - 4] = arguments[_i];
85
105
  }
86
- return __awaiter(void 0, __spreadArray([host_1, username_1, password_1, db_name_1], args_1, true), void 0, function (host, username, password, db_name, db_engine) {
87
- var client, q, e_1;
106
+ return __awaiter(void 0, __spreadArray([host_1, username_1, password_1, db_name_1], args_1, true), void 0, function (host, username, password, db_name, db_engine, timeout, ca_cert, cert, key) {
107
+ var client, e_1, q, e_2;
88
108
  if (db_engine === void 0) { db_engine = 'ENGINE=Atomic'; }
89
109
  return __generator(this, function (_a) {
90
110
  switch (_a.label) {
91
111
  case 0:
92
- client = connect(host, username, password);
93
- q = "CREATE DATABASE IF NOT EXISTS \"".concat(db_name, "\" ").concat(db_engine);
112
+ client = connect(host, username, password, undefined, timeout, ca_cert, cert, key);
94
113
  _a.label = 1;
95
114
  case 1:
96
115
  _a.trys.push([1, 3, , 4]);
97
- return [4 /*yield*/, client.exec({
98
- query: q,
99
- clickhouse_settings: {
100
- wait_end_of_query: 1,
101
- },
102
- })];
116
+ return [4 /*yield*/, client.ping()];
103
117
  case 2:
104
118
  _a.sent();
105
119
  return [3 /*break*/, 4];
106
120
  case 3:
107
121
  e_1 = _a.sent();
108
- log('error', "can't create the database ".concat(db_name, "."), e_1.message);
122
+ log('error', "Failed to connect to ClickHouse", e_1.message);
109
123
  process.exit(1);
110
124
  return [3 /*break*/, 4];
111
- case 4: return [4 /*yield*/, client.close()];
125
+ case 4:
126
+ q = "CREATE DATABASE IF NOT EXISTS \"".concat(db_name, "\" ").concat(db_engine);
127
+ _a.label = 5;
112
128
  case 5:
129
+ _a.trys.push([5, 7, , 8]);
130
+ return [4 /*yield*/, client.exec({
131
+ query: q,
132
+ clickhouse_settings: {
133
+ wait_end_of_query: 1,
134
+ },
135
+ })];
136
+ case 6:
137
+ _a.sent();
138
+ return [3 /*break*/, 8];
139
+ case 7:
140
+ e_2 = _a.sent();
141
+ log('error', "can't create the database ".concat(db_name, "."), e_2.message);
142
+ process.exit(1);
143
+ return [3 /*break*/, 8];
144
+ case 8: return [4 /*yield*/, client.close()];
145
+ case 9:
113
146
  _a.sent();
114
147
  return [2 /*return*/];
115
148
  }
@@ -117,7 +150,7 @@ var create_db = function (host_1, username_1, password_1, db_name_1) {
117
150
  });
118
151
  };
119
152
  var init_migration_table = function (client) { return __awaiter(void 0, void 0, void 0, function () {
120
- var q, e_2;
153
+ var q, e_3;
121
154
  return __generator(this, function (_a) {
122
155
  switch (_a.label) {
123
156
  case 0:
@@ -135,8 +168,8 @@ var init_migration_table = function (client) { return __awaiter(void 0, void 0,
135
168
  _a.sent();
136
169
  return [3 /*break*/, 4];
137
170
  case 3:
138
- e_2 = _a.sent();
139
- log('error', "can't create the _migrations table.", e_2.message);
171
+ e_3 = _a.sent();
172
+ log('error', "can't create the _migrations table.", e_3.message);
140
173
  process.exit(1);
141
174
  return [3 /*break*/, 4];
142
175
  case 4: return [2 /*return*/];
@@ -154,14 +187,15 @@ var get_migrations = function (migrations_home) {
154
187
  }
155
188
  var migrations = [];
156
189
  files.forEach(function (file) {
190
+ // Manage only .sql files.
191
+ if (!file.endsWith('.sql')) {
192
+ return;
193
+ }
157
194
  var version = Number(file.split('_')[0]);
158
195
  if (!version) {
159
196
  log('error', "a migration name should start from number, example: 1_init.sql. Please check, if the migration ".concat(file, " is named correctly"));
160
197
  process.exit(1);
161
198
  }
162
- // Manage only .sql files.
163
- if (!file.endsWith('.sql'))
164
- return;
165
199
  migrations.push({
166
200
  version: version,
167
201
  file: file,
@@ -175,7 +209,7 @@ var get_migrations = function (migrations_home) {
175
209
  return migrations;
176
210
  };
177
211
  var apply_migrations = function (client, migrations, migrations_home) { return __awaiter(void 0, void 0, void 0, function () {
178
- var migration_query_result, resultSet, e_3, migrations_applied, applied_migrations, _i, migrations_1, migration_1, content, checksum, queries, sets, _a, queries_1, query, e_4, e_5;
212
+ var migration_query_result, resultSet, e_4, migrations_applied, applied_migrations, _i, migrations_1, migration_1, content, checksum, queries, sets, _a, queries_1, query, e_5, e_6;
179
213
  return __generator(this, function (_b) {
180
214
  switch (_b.label) {
181
215
  case 0:
@@ -194,8 +228,8 @@ var apply_migrations = function (client, migrations, migrations_home) { return _
194
228
  migration_query_result = _b.sent();
195
229
  return [3 /*break*/, 5];
196
230
  case 4:
197
- e_3 = _b.sent();
198
- log('error', "can't select data from the _migrations table.", e_3.message);
231
+ e_4 = _b.sent();
232
+ log('error', "can't select data from the _migrations table.", e_4.message);
199
233
  process.exit(1);
200
234
  return [3 /*break*/, 5];
201
235
  case 5:
@@ -251,11 +285,11 @@ var apply_migrations = function (client, migrations, migrations_home) { return _
251
285
  _b.sent();
252
286
  return [3 /*break*/, 11];
253
287
  case 10:
254
- e_4 = _b.sent();
288
+ e_5 = _b.sent();
255
289
  if (applied_migrations) {
256
290
  log('info', "The migration(s) ".concat(applied_migrations, " was successfully applied!"));
257
291
  }
258
- log('error', "the migrations ".concat(migration_1.file, " has an error. Please, fix it (be sure that already executed parts of the migration would not be run second time) and re-run migration script."), e_4.message);
292
+ log('error', "the migrations ".concat(migration_1.file, " has an error. Please, fix it (be sure that already executed parts of the migration would not be run second time) and re-run migration script."), e_5.message);
259
293
  process.exit(1);
260
294
  return [3 /*break*/, 11];
261
295
  case 11:
@@ -272,8 +306,8 @@ var apply_migrations = function (client, migrations, migrations_home) { return _
272
306
  _b.sent();
273
307
  return [3 /*break*/, 15];
274
308
  case 14:
275
- e_5 = _b.sent();
276
- log('error', "can't insert a data into the table _migrations.", e_5.message);
309
+ e_6 = _b.sent();
310
+ log('error', "can't insert a data into the table _migrations.", e_6.message);
277
311
  process.exit(1);
278
312
  return [3 /*break*/, 15];
279
313
  case 15:
@@ -293,16 +327,16 @@ var apply_migrations = function (client, migrations, migrations_home) { return _
293
327
  }
294
328
  });
295
329
  }); };
296
- var migration = function (migrations_home, host, username, password, db_name, db_engine, timeout) { return __awaiter(void 0, void 0, void 0, function () {
330
+ var migration = function (migrations_home, host, username, password, db_name, db_engine, timeout, ca_cert, cert, key) { return __awaiter(void 0, void 0, void 0, function () {
297
331
  var migrations, client;
298
332
  return __generator(this, function (_a) {
299
333
  switch (_a.label) {
300
334
  case 0:
301
335
  migrations = get_migrations(migrations_home);
302
- return [4 /*yield*/, create_db(host, username, password, db_name, db_engine)];
336
+ return [4 /*yield*/, create_db(host, username, password, db_name, db_engine, timeout, ca_cert, cert, key)];
303
337
  case 1:
304
338
  _a.sent();
305
- client = connect(host, username, password, db_name, timeout);
339
+ client = connect(host, username, password, db_name, timeout, ca_cert, cert, key);
306
340
  return [4 /*yield*/, init_migration_table(client)];
307
341
  case 2:
308
342
  _a.sent();
@@ -319,7 +353,7 @@ var migration = function (migrations_home, host, username, password, db_name, db
319
353
  exports.migration = migration;
320
354
  var migrate = function () {
321
355
  var program = new commander_1.Command();
322
- program.name('clickhouse-migrations').description('ClickHouse migrations.').version('1.0.4');
356
+ program.name('clickhouse-migrations').description('ClickHouse migrations.').version('1.1.0');
323
357
  program
324
358
  .command('migrate')
325
359
  .description('Apply migrations.')
@@ -330,10 +364,13 @@ var migrate = function () {
330
364
  .requiredOption('--migrations-home <dir>', "Migrations' directory", process.env.CH_MIGRATIONS_HOME)
331
365
  .option('--db-engine <value>', 'ON CLUSTER and/or ENGINE clauses for database (default: "ENGINE=Atomic")', process.env.CH_MIGRATIONS_DB_ENGINE)
332
366
  .option('--timeout <value>', 'Client request timeout (milliseconds, default value 30000)', process.env.CH_MIGRATIONS_TIMEOUT)
367
+ .option('--ca-cert <path>', 'CA certificate file path', process.env.CH_MIGRATIONS_CA_CERT)
368
+ .option('--cert <path>', 'Client certificate file path', process.env.CH_MIGRATIONS_CERT)
369
+ .option('--key <path>', 'Client key file path', process.env.CH_MIGRATIONS_KEY)
333
370
  .action(function (options) { return __awaiter(void 0, void 0, void 0, function () {
334
371
  return __generator(this, function (_a) {
335
372
  switch (_a.label) {
336
- case 0: return [4 /*yield*/, migration(options.migrationsHome, options.host, options.user, options.password, options.db, options.dbEngine, options.timeout)];
373
+ case 0: return [4 /*yield*/, migration(options.migrationsHome, options.host, options.user, options.password, options.db, options.dbEngine, options.timeout, options.caCert, options.cert, options.key)];
337
374
  case 1:
338
375
  _a.sent();
339
376
  return [2 /*return*/];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clickhouse-migrations",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "ClickHouse Migrations",
5
5
  "bin": {
6
6
  "clickhouse-migrations": "lib/cli.js"
@@ -17,6 +17,8 @@
17
17
  "scripts": {
18
18
  "build": "rm lib/*; tsc",
19
19
  "test": "jest --config jestconfig.json",
20
+ "test:unit": "jest --config jestconfig.json --testPathPatterns=\"\\.(unit|integration)\\.test\\.ts$\"",
21
+ "test:e2e": "jest --config jestconfig.json --testPathPatterns=\"\\.e2e\\.test\\.ts$\"",
20
22
  "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
21
23
  "lint": "eslint ./src",
22
24
  "prepare": "npm run build",
@@ -26,23 +28,23 @@
26
28
  "postversion": "git push && git push --tags"
27
29
  },
28
30
  "dependencies": {
29
- "@clickhouse/client": "^1.10.1",
30
- "commander": "^13.1.0"
31
+ "@clickhouse/client": "^1.12.0",
32
+ "commander": "^14.0.0"
31
33
  },
32
34
  "devDependencies": {
33
- "@eslint/js": "^9.18.0",
34
- "@types/jest": "^29.5.14",
35
- "@types/node": "^22.10.7",
36
- "@typescript-eslint/eslint-plugin": "^8.21.0",
37
- "@typescript-eslint/parser": "^8.21.0",
38
- "eslint": "^9.18.0",
39
- "eslint-config-prettier": "^10.0.1",
40
- "eslint-plugin-prettier": "^5.2.3",
41
- "jest": "^29.7.0",
42
- "prettier": "^3.4.2",
43
- "ts-jest": "^29.2.5",
44
- "typescript": "^5.7.3",
45
- "typescript-eslint": "^8.21.0"
35
+ "@eslint/js": "^9.33.0",
36
+ "@types/jest": "^30.0.0",
37
+ "@types/node": "^24.2.1",
38
+ "@typescript-eslint/eslint-plugin": "^8.39.0",
39
+ "@typescript-eslint/parser": "^8.39.0",
40
+ "eslint": "^9.33.0",
41
+ "eslint-config-prettier": "^10.1.8",
42
+ "eslint-plugin-prettier": "^5.5.4",
43
+ "jest": "^30.0.5",
44
+ "prettier": "^3.6.2",
45
+ "ts-jest": "^29.4.1",
46
+ "typescript": "^5.9.2",
47
+ "typescript-eslint": "^8.39.0"
46
48
  },
47
49
  "files": [
48
50
  "lib/**/*"