kourou 0.19.2 → 0.20.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 +148 -108
- package/lib/commands/app/scaffold.d.ts +2 -0
- package/lib/commands/app/scaffold.js +30 -7
- package/lib/commands/app/start-services.js +7 -7
- package/lib/commands/collection/export.d.ts +1 -0
- package/lib/commands/collection/export.js +24 -7
- package/lib/commands/collection/import.js +4 -4
- package/lib/commands/config/diff.js +5 -5
- package/lib/commands/document/search.js +1 -1
- package/lib/commands/es/migrate.js +3 -3
- package/lib/commands/file/decrypt.js +2 -2
- package/lib/commands/file/encrypt.js +2 -2
- package/lib/commands/file/test.js +2 -2
- package/lib/commands/import.js +7 -7
- package/lib/commands/index/export.d.ts +2 -0
- package/lib/commands/index/export.js +13 -5
- package/lib/commands/index/import.js +4 -4
- package/lib/commands/instance/kill.js +6 -6
- package/lib/commands/instance/list.js +1 -1
- package/lib/commands/instance/logs.js +3 -3
- package/lib/commands/instance/spawn.js +10 -10
- package/lib/commands/profile/export.js +2 -2
- package/lib/commands/profile/import.js +2 -2
- package/lib/commands/realtime/subscribe.js +1 -1
- package/lib/commands/role/export.js +2 -3
- package/lib/commands/role/import.js +2 -2
- package/lib/commands/sdk/execute.js +2 -2
- package/lib/commands/sdk/query.js +1 -1
- package/lib/commands/user/export-mappings.js +2 -2
- package/lib/commands/user/export.js +4 -4
- package/lib/commands/user/import-mappings.js +1 -1
- package/lib/commands/user/import.js +2 -2
- package/lib/commands/vault/add.js +2 -2
- package/lib/commands/vault/decrypt.js +2 -2
- package/lib/commands/vault/encrypt.js +2 -2
- package/lib/commands/vault/show.js +3 -3
- package/lib/commands/vault/test.js +1 -1
- package/lib/common.d.ts +17 -0
- package/lib/common.js +35 -4
- package/lib/hooks/command_not_found/api-action.js +2 -2
- package/lib/support/dump-collection.d.ts +1 -1
- package/lib/support/dump-collection.js +211 -61
- package/lib/support/editor.js +3 -3
- package/lib/support/execute.js +1 -1
- package/lib/support/kuzzle.d.ts +1 -1
- package/lib/support/kuzzle.js +1 -0
- package/lib/support/restore-collection.js +5 -5
- package/lib/support/restore-securities.js +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +21 -19
- package/templates.tgz +0 -0
- package/lib/commands/es/snapshot/restore.d.ts +0 -18
- package/lib/commands/es/snapshot/restore.js +0 -52
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
5
|
-
const query_1 = tslib_1.__importDefault(require("../../commands/sdk/query"));
|
|
4
|
+
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
5
|
+
const query_1 = (0, tslib_1.__importDefault)(require("../../commands/sdk/query"));
|
|
6
6
|
/**
|
|
7
7
|
* Hooks that run the corresponding API action with sdk:query.
|
|
8
8
|
*
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function dumpCollectionData(sdk: any, index: string, collection: string, batchSize: number, destPath: string, query?: any, format?: string): Promise<
|
|
1
|
+
export declare function dumpCollectionData(sdk: any, index: string, collection: string, batchSize: number, destPath: string, query?: any, format?: string, fields?: string[]): Promise<void>;
|
|
2
2
|
export declare function dumpCollectionMappings(sdk: any, index: string, collection: string, destPath: string, format?: string): Promise<void>;
|
|
@@ -2,76 +2,226 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.dumpCollectionMappings = exports.dumpCollectionData = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
6
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
-
const cli_ux_1 = tslib_1.__importDefault(require("cli-ux"));
|
|
8
|
-
const ndjson_1 = tslib_1.__importDefault(require("ndjson"));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
6
|
+
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
7
|
+
const cli_ux_1 = (0, tslib_1.__importDefault)(require("cli-ux"));
|
|
8
|
+
const ndjson_1 = (0, tslib_1.__importDefault)(require("ndjson"));
|
|
9
|
+
const common_1 = require("../common");
|
|
10
|
+
/**
|
|
11
|
+
* Flatten an object transform:
|
|
12
|
+
* {
|
|
13
|
+
* title: "kuzzle",
|
|
14
|
+
* info : {
|
|
15
|
+
* tag: "news"
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* Into an object like:
|
|
20
|
+
* {
|
|
21
|
+
* title: "kuzzle",
|
|
22
|
+
* info.tag: news
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* @param {Object} target the object we have to flatten
|
|
26
|
+
* @returns {Object} the flattened object
|
|
27
|
+
*/
|
|
28
|
+
function flattenObject(target) {
|
|
29
|
+
const output = {};
|
|
30
|
+
flattenStep(output, target);
|
|
31
|
+
return output;
|
|
32
|
+
}
|
|
33
|
+
function flattenStep(output, object, prev = null) {
|
|
34
|
+
const keys = Object.keys(object);
|
|
35
|
+
for (let i = 0; i < keys.length; i++) {
|
|
36
|
+
const key = keys[i];
|
|
37
|
+
const value = object[key];
|
|
38
|
+
const newKey = prev ? prev + '.' + key : key;
|
|
39
|
+
if (Object.prototype.toString.call(value) === '[object Object]') {
|
|
40
|
+
output[newKey] = value;
|
|
41
|
+
flattenStep(output, value, newKey);
|
|
42
|
+
}
|
|
43
|
+
output[newKey] = value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
class AbstractDumper {
|
|
47
|
+
constructor(sdk, index, collection, batchSize, destPath, query = {}) {
|
|
48
|
+
this.sdk = sdk;
|
|
49
|
+
this.index = index;
|
|
50
|
+
this.collection = collection;
|
|
51
|
+
this.batchSize = batchSize;
|
|
52
|
+
this.destPath = destPath;
|
|
53
|
+
this.query = query;
|
|
54
|
+
this.collectionDir = path_1.default.join(this.destPath, this.collection);
|
|
55
|
+
this.options = {
|
|
56
|
+
scroll: '2s',
|
|
57
|
+
size: batchSize
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* One-shot call before the dump. Can be used to
|
|
62
|
+
* perform setup operations before dumping.
|
|
63
|
+
*
|
|
64
|
+
* @returns void
|
|
65
|
+
*/
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
67
|
+
async setup() { }
|
|
68
|
+
/**
|
|
69
|
+
* One-shot call before iterating over the data. Can be
|
|
70
|
+
* used to write the header of the dumped output.
|
|
71
|
+
*/
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
73
|
+
async writeHeader() { }
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
75
|
+
async tearDown() { }
|
|
76
|
+
/**
|
|
77
|
+
* The loop that iterates over the documents of the collection and
|
|
78
|
+
* calls all the other hooks.
|
|
79
|
+
*
|
|
80
|
+
* @returns a promise resolving when the dump is finished.
|
|
81
|
+
*/
|
|
82
|
+
async dump() {
|
|
83
|
+
this.filename = path_1.default.join(this.collectionDir, `documents.${this.fileExtension}`);
|
|
84
|
+
this.writeStream = fs_1.default.createWriteStream(this.filename);
|
|
85
|
+
const waitWrite = new Promise((resolve, reject) => this.writeStream ? this.writeStream.on('finish', resolve) : reject());
|
|
86
|
+
this.writeStream.on('error', error => {
|
|
87
|
+
throw error;
|
|
88
|
+
});
|
|
89
|
+
await this.setup();
|
|
90
|
+
await this.writeHeader();
|
|
91
|
+
let results = await this.sdk.document.search(this.index, this.collection, { query: this.query }, this.options);
|
|
92
|
+
const progressBar = cli_ux_1.default.progress({
|
|
93
|
+
format: `Dumping ${this.collection} |{bar}| {percentage}% || {value}/{total} documents`
|
|
94
|
+
});
|
|
95
|
+
progressBar.start(results.total, 0);
|
|
96
|
+
do {
|
|
97
|
+
progressBar.update(results.fetched);
|
|
98
|
+
for (const hit of results.hits) {
|
|
99
|
+
await this.onResult({
|
|
100
|
+
_id: hit._id,
|
|
101
|
+
_source: hit._source
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
} while ((results = await results.next()));
|
|
105
|
+
await this.tearDown();
|
|
106
|
+
progressBar.stop();
|
|
107
|
+
this.writeStream.end();
|
|
108
|
+
return waitWrite;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
class JSONLDumper extends AbstractDumper {
|
|
112
|
+
constructor() {
|
|
113
|
+
super(...arguments);
|
|
114
|
+
this.ndjsonStream = ndjson_1.default.stringify();
|
|
115
|
+
}
|
|
116
|
+
async setup() {
|
|
117
|
+
this.ndjsonStream.on('data', (line) => {
|
|
118
|
+
if (!this.writeStream) {
|
|
119
|
+
throw new Error('Cannot write data: WriteStream is not initialized.');
|
|
120
|
+
}
|
|
121
|
+
this.writeStream.write(line);
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
async writeHeader() {
|
|
126
|
+
await this.writeLine({ type: 'collection', index: this.index, collection: this.collection });
|
|
127
|
+
}
|
|
128
|
+
writeLine(content) {
|
|
20
129
|
return new Promise(resolve => {
|
|
21
|
-
if (ndjsonStream.write(content)) {
|
|
130
|
+
if (this.ndjsonStream.write(content)) {
|
|
22
131
|
resolve(undefined);
|
|
23
132
|
}
|
|
24
133
|
else {
|
|
25
|
-
ndjsonStream.once('drain', resolve);
|
|
134
|
+
this.ndjsonStream.once('drain', resolve);
|
|
26
135
|
}
|
|
27
136
|
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const rawDocuments = {
|
|
43
|
-
[index]: {
|
|
44
|
-
[collection]: []
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
do {
|
|
48
|
-
progressBar.update(results.fetched);
|
|
49
|
-
for (const hit of results.hits) {
|
|
50
|
-
let document = null;
|
|
51
|
-
if (format.toLocaleLowerCase() === 'jsonl') {
|
|
52
|
-
document = {
|
|
53
|
-
_id: hit._id,
|
|
54
|
-
body: hit._source
|
|
55
|
-
};
|
|
56
|
-
await writeLine(document);
|
|
137
|
+
}
|
|
138
|
+
onResult(document) {
|
|
139
|
+
return this.writeLine({ _id: document._id, body: document._source });
|
|
140
|
+
}
|
|
141
|
+
get fileExtension() {
|
|
142
|
+
return 'jsonl';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
class KuzzleDumper extends JSONLDumper {
|
|
146
|
+
constructor() {
|
|
147
|
+
super(...arguments);
|
|
148
|
+
this.rawDocuments = {
|
|
149
|
+
[this.index]: {
|
|
150
|
+
[this.collection]: []
|
|
57
151
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
get fileExtension() {
|
|
155
|
+
return 'json';
|
|
156
|
+
}
|
|
157
|
+
async onResult(document) {
|
|
158
|
+
this.rawDocuments[this.index][this.collection].push({
|
|
159
|
+
index: {
|
|
160
|
+
_id: document._id
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
this.rawDocuments[this.index][this.collection].push(document._source);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
tearDown() {
|
|
167
|
+
return this.writeLine(this.rawDocuments);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
class CSVDumper extends AbstractDumper {
|
|
171
|
+
constructor(sdk, index, collection, batchSize, destPath, query = {}, fields, separator = ',') {
|
|
172
|
+
super(sdk, index, collection, batchSize, destPath, query);
|
|
173
|
+
this.fields = fields;
|
|
174
|
+
this.separator = separator;
|
|
175
|
+
}
|
|
176
|
+
get fileExtension() {
|
|
177
|
+
return 'csv';
|
|
178
|
+
}
|
|
179
|
+
async setup() {
|
|
180
|
+
if (!this.fields.length) {
|
|
181
|
+
// If no field has been selected, then all fields are selected.
|
|
182
|
+
const mappings = await this.sdk.collection.getMapping(this.index, this.collection);
|
|
183
|
+
if (!mappings.properties) {
|
|
184
|
+
return;
|
|
65
185
|
}
|
|
186
|
+
this.fields = Object.keys(flattenObject(mappings.properties));
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// Delete '_id' from the selected fields, since IDs are
|
|
190
|
+
// _always_ exported.
|
|
191
|
+
if (this.fields.includes('_id')) {
|
|
192
|
+
this.fields.splice(this.fields.indexOf('_id'), 1);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
writeHeader() {
|
|
197
|
+
return this.writeLine(['_id', ...this.fields].join(this.separator));
|
|
198
|
+
}
|
|
199
|
+
async writeLine(line) {
|
|
200
|
+
if (!this.writeStream) {
|
|
201
|
+
throw new Error('Cannot write data: WriteStream is not initialized.');
|
|
66
202
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
203
|
+
this.writeStream.write(line);
|
|
204
|
+
this.writeStream.write('\n');
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
onResult(document) {
|
|
208
|
+
const values = [document._id, ...(0, common_1.pickValues)(document._source, this.fields)];
|
|
209
|
+
return this.writeLine(values.join(this.separator));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async function dumpCollectionData(sdk, index, collection, batchSize, destPath, query = {}, format = 'jsonl', fields = []) {
|
|
213
|
+
let dumper;
|
|
214
|
+
switch (format.toLowerCase()) {
|
|
215
|
+
case 'jsonl':
|
|
216
|
+
dumper = new JSONLDumper(sdk, index, collection, batchSize, destPath, query);
|
|
217
|
+
return dumper.dump();
|
|
218
|
+
case 'csv':
|
|
219
|
+
dumper = new CSVDumper(sdk, index, collection, batchSize, destPath, query, fields);
|
|
220
|
+
return dumper.dump();
|
|
221
|
+
default:
|
|
222
|
+
dumper = new KuzzleDumper(sdk, index, collection, batchSize, destPath, query);
|
|
223
|
+
return dumper.dump();
|
|
224
|
+
}
|
|
75
225
|
}
|
|
76
226
|
exports.dumpCollectionData = dumpCollectionData;
|
|
77
227
|
async function dumpCollectionMappings(sdk, index, collection, destPath, format = 'jsonl') {
|
package/lib/support/editor.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Editor = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
5
|
+
const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
6
6
|
const child_process_1 = require("child_process");
|
|
7
|
-
const tmp_1 = tslib_1.__importDefault(require("tmp"));
|
|
7
|
+
const tmp_1 = (0, tslib_1.__importDefault)(require("tmp"));
|
|
8
8
|
class Editor {
|
|
9
9
|
constructor(content = '', options = {}) {
|
|
10
10
|
this._content = content;
|
|
@@ -29,7 +29,7 @@ class Editor {
|
|
|
29
29
|
run() {
|
|
30
30
|
process.env.EDITOR = process.env.EDITOR || this.defaultEditor;
|
|
31
31
|
const editor = process.env.EDITOR;
|
|
32
|
-
const response = child_process_1.spawnSync(editor, [this.tmpFile.name], { stdio: 'inherit' });
|
|
32
|
+
const response = (0, child_process_1.spawnSync)(editor, [this.tmpFile.name], { stdio: 'inherit' });
|
|
33
33
|
if (response.status !== 0) {
|
|
34
34
|
// eslint-disable-next-line
|
|
35
35
|
console.error(response.stdout);
|
package/lib/support/execute.js
CHANGED
|
@@ -26,7 +26,7 @@ function execute(...args) {
|
|
|
26
26
|
options = args.splice(args.length - 1)[0];
|
|
27
27
|
}
|
|
28
28
|
const [command, ...commandArgs] = args;
|
|
29
|
-
const process = child_process_1.spawn(command, commandArgs, options);
|
|
29
|
+
const process = (0, child_process_1.spawn)(command, commandArgs, options);
|
|
30
30
|
let stdout = '';
|
|
31
31
|
let stderr = '';
|
|
32
32
|
// eslint-disable-next-line
|
package/lib/support/kuzzle.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export declare class KuzzleSDK {
|
|
|
40
40
|
get document(): import("kuzzle-sdk").DocumentController;
|
|
41
41
|
get collection(): import("kuzzle-sdk").CollectionController;
|
|
42
42
|
get index(): import("kuzzle-sdk").IndexController;
|
|
43
|
-
get security():
|
|
43
|
+
get security(): import("kuzzle-sdk/src/controllers/Security").SecurityController;
|
|
44
44
|
get auth(): import("kuzzle-sdk").AuthController;
|
|
45
45
|
get server(): any;
|
|
46
46
|
get realtime(): import("kuzzle-sdk").RealtimeController;
|
package/lib/support/kuzzle.js
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.restoreCollectionMappings = exports.restoreCollectionData = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
-
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
7
|
-
const
|
|
5
|
+
const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
|
|
6
|
+
const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
7
|
+
const ndjson_1 = (0, tslib_1.__importDefault)(require("ndjson"));
|
|
8
8
|
function handleError(log, dumpFile, error) {
|
|
9
9
|
if (error.status === 206) {
|
|
10
10
|
const errorFile = `${dumpFile.split('.').slice(0, -1).join('.')}-errors.jsonl`;
|
|
11
11
|
const writeStream = fs_1.default.createWriteStream(errorFile, { flags: 'a' });
|
|
12
|
-
const serialize =
|
|
12
|
+
const serialize = ndjson_1.default.stringify().pipe(writeStream);
|
|
13
13
|
serialize.on('data', (line) => (writeStream.write(line)));
|
|
14
14
|
for (const partialError of error.errors) {
|
|
15
15
|
serialize.write(partialError);
|
|
@@ -37,7 +37,7 @@ async function restoreCollectionData(sdk, log, batchSize, dumpFile, index, colle
|
|
|
37
37
|
let headerSkipped = false;
|
|
38
38
|
let documents = [];
|
|
39
39
|
const readStream = fs_1.default.createReadStream(dumpFile)
|
|
40
|
-
.pipe(
|
|
40
|
+
.pipe(ndjson_1.default.parse())
|
|
41
41
|
.on('data', (obj) => {
|
|
42
42
|
if (headerSkipped) {
|
|
43
43
|
documents.push(obj);
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.restoreUsers = exports.restoreProfiles = exports.restoreRoles = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
6
|
-
const bluebird_1 = tslib_1.__importDefault(require("bluebird"));
|
|
5
|
+
const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
|
|
6
|
+
const bluebird_1 = (0, tslib_1.__importDefault)(require("bluebird"));
|
|
7
7
|
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
|
8
8
|
async function restoreRoles(kommand, dump, preserveAnonymous = false) {
|
|
9
9
|
if (dump.type !== 'roles') {
|