@algolia/cli 4.0.8 → 5.10.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.
@@ -1,61 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const algolia = require('algoliasearch');
4
- const Base = require('./Base.js');
5
-
6
- class ExportRulesScript extends Base {
7
- constructor() {
8
- super();
9
- // Bind class methods
10
- this.getOutputPath = this.getOutputPath.bind(this);
11
- this.start = this.start.bind(this);
12
- // Define validation constants
13
- this.message =
14
- '\nExample: $ algolia exportrules -a algoliaappid -k algoliaapikey -n algoliaindexname -o outputpath\n\n';
15
- this.params = ['algoliaappid', 'algoliaapikey', 'algoliaindexname'];
16
- }
17
-
18
- getOutputPath(outputpath, indexName) {
19
- const defaultFilename = `${indexName}-rules.json`;
20
- const defaultFilepath = path.resolve(process.cwd(), defaultFilename);
21
- // Process output filepath
22
- const filepath =
23
- outputpath !== null ? this.normalizePath(outputpath) : defaultFilepath;
24
- // Validate filepath targets valid directory
25
- const dir = path.dirname(filepath);
26
- if (!fs.lstatSync(dir).isDirectory()) {
27
- throw new Error(
28
- `Output path must target valid directory. Eg. ${defaultFilepath}`
29
- );
30
- }
31
- return filepath;
32
- }
33
-
34
- async start(program) {
35
- try {
36
- // Validate command; if invalid display help text and exit
37
- this.validate(program, this.message, this.params);
38
-
39
- // Config params
40
- const appId = program.algoliaappid;
41
- const apiKey = program.algoliaapikey;
42
- const indexName = program.algoliaindexname;
43
- const outputpath = program.outputpath || null;
44
-
45
- const filepath = this.getOutputPath(outputpath, indexName);
46
-
47
- // Instantiate Algolia index
48
- const client = algolia(appId, apiKey);
49
- const index = client.initIndex(indexName);
50
- // Get index settings
51
- const rules = await index.exportRules();
52
- fs.writeFileSync(filepath, JSON.stringify(rules));
53
- return console.log(`Done writing ${filepath}`);
54
- } catch (e) {
55
- throw e;
56
- }
57
- }
58
- }
59
-
60
- const exportRulesScript = new ExportRulesScript();
61
- module.exports = exportRulesScript;
@@ -1,61 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const algolia = require('algoliasearch');
4
- const Base = require('./Base.js');
5
-
6
- class ExportSynonymsScript extends Base {
7
- constructor() {
8
- super();
9
- // Bind class methods
10
- this.getOutputPath = this.getOutputPath.bind(this);
11
- this.start = this.start.bind(this);
12
- // Define validation constants
13
- this.message =
14
- '\nExample: $ algolia exportsynonyms -a algoliaappid -k algoliaapikey -n algoliaindexname -o outputpath\n\n';
15
- this.params = ['algoliaappid', 'algoliaapikey', 'algoliaindexname'];
16
- }
17
-
18
- getOutputPath(outputpath, indexName) {
19
- const defaultFilename = `${indexName}-synonyms.json`;
20
- const defaultFilepath = path.resolve(process.cwd(), defaultFilename);
21
- // Process output filepath
22
- const filepath =
23
- outputpath !== null ? this.normalizePath(outputpath) : defaultFilepath;
24
- // Validate filepath targets valid directory
25
- const dir = path.dirname(filepath);
26
- if (!fs.lstatSync(dir).isDirectory()) {
27
- throw new Error(
28
- `Output path must target valid directory. Eg. ${defaultFilepath}`
29
- );
30
- }
31
- return filepath;
32
- }
33
-
34
- async start(program) {
35
- try {
36
- // Validate command; if invalid display help text and exit
37
- this.validate(program, this.message, this.params);
38
-
39
- // Config params
40
- const appId = program.algoliaappid;
41
- const apiKey = program.algoliaapikey;
42
- const indexName = program.algoliaindexname;
43
- const outputpath = program.outputpath || null;
44
-
45
- const filepath = this.getOutputPath(outputpath, indexName);
46
-
47
- // Instantiate Algolia index
48
- const client = algolia(appId, apiKey);
49
- const index = client.initIndex(indexName);
50
- // Get index settings
51
- const synonyms = await index.exportSynonyms();
52
- fs.writeFileSync(filepath, JSON.stringify(synonyms));
53
- return console.log(`Done writing ${filepath}`);
54
- } catch (e) {
55
- throw e;
56
- }
57
- }
58
- }
59
-
60
- const exportSynonymsScript = new ExportSynonymsScript();
61
- module.exports = exportSynonymsScript;
@@ -1,38 +0,0 @@
1
- const algolia = require('algoliasearch');
2
- const Base = require('./Base.js');
3
-
4
- class GetSettingsScript extends Base {
5
- constructor() {
6
- super();
7
- // Bind class methods
8
- this.start = this.start.bind(this);
9
- // Define validation constants
10
- this.message =
11
- '\nExample: $ algolia getsettings -a algoliaappid -k algoliaapikey -n algoliaindexname\n\n';
12
- this.params = ['algoliaappid', 'algoliaapikey', 'algoliaindexname'];
13
- }
14
-
15
- async start(program) {
16
- try {
17
- // Validate command; if invalid display help text and exit
18
- this.validate(program, this.message, this.params);
19
-
20
- // Config params
21
- const appId = program.algoliaappid;
22
- const apiKey = program.algoliaapikey;
23
- const indexName = program.algoliaindexname;
24
-
25
- // Instantiate Algolia index
26
- const client = algolia(appId, apiKey);
27
- const index = client.initIndex(indexName);
28
- // Get index settings
29
- const settings = await index.getSettings();
30
- return console.log(JSON.stringify(settings));
31
- } catch (e) {
32
- throw e;
33
- }
34
- }
35
- }
36
-
37
- const getSettingsScript = new GetSettingsScript();
38
- module.exports = getSettingsScript;
@@ -1,379 +0,0 @@
1
- const fs = require('fs');
2
- const JSONStream = require('JSONStream');
3
- const through = require('through');
4
- const transform = require('stream-transform');
5
- const Batch = require('batch-stream');
6
- const async = require('async');
7
- const csv = require('csvtojson');
8
- const regexParser = require('regex-parser');
9
- const chalk = require('chalk');
10
- const algolia = require('algoliasearch');
11
- const Base = require('./Base.js');
12
-
13
- class ImportScript extends Base {
14
- constructor() {
15
- super();
16
- // Bind class methods
17
- this.defaultTransformations = this.defaultTransformations.bind(this);
18
- this.suggestions = this.suggestions.bind(this);
19
- this.checkMemoryUsage = this.checkMemoryUsage.bind(this);
20
- this.handleHighMemoryUsage = this.handleHighMemoryUsage.bind(this);
21
- this.handleExtremeMemoryUsage = this.handleExtremeMemoryUsage.bind(this);
22
- this.setIndex = this.setIndex.bind(this);
23
- this.setTransformations = this.setTransformations.bind(this);
24
- this.setCsvOptions = this.setCsvOptions.bind(this);
25
- this.conditionallyParseCsv = this.conditionallyParseCsv.bind(this);
26
- this.setBatchSize = this.setBatchSize.bind(this);
27
- this.estimateBatchSize = this.estimateBatchSize.bind(this);
28
- this.updateBatchSize = this.updateBatchSize.bind(this);
29
- this.importToAlgolia = this.importToAlgolia.bind(this);
30
- this.retryImport = this.retryImport.bind(this);
31
- this.indexFiles = this.indexFiles.bind(this);
32
- this.start = this.start.bind(this);
33
- // Define validation constants
34
- this.message =
35
- '\nExample: $ algolia import -s sourcefilepath -a algoliaappid -k algoliaapikey -n algoliaindexname -b batchsize -t transformationfilepath -m maxconcurrency -p csvtojsonparams\n\n';
36
- this.params = [
37
- 'sourcefilepath',
38
- 'algoliaappid',
39
- 'algoliaapikey',
40
- 'algoliaindexname',
41
- ];
42
- }
43
-
44
- defaultTransformations(data, cb) {
45
- cb(null, data);
46
- }
47
-
48
- suggestions() {
49
- let output = `\nConsider reducing <batchSize> (currently ${
50
- this.batchSize
51
- }).`;
52
- if (this.maxConcurrency > 1)
53
- output += `\nConsider reducing <maxConcurrency> (currently ${
54
- this.maxConcurrency
55
- }).`;
56
- return output;
57
- }
58
-
59
- checkMemoryUsage() {
60
- // Exit early if high memory usage warning issued too recently
61
- if (this.highMemoryUsage) return false;
62
- // Get memory usage
63
- const { usedMb, percentUsed } = this.getMemoryUsage();
64
- // Handle if heap usage exceeds n% of estimated allocation for node process
65
- if (percentUsed >= 70) this.handleHighMemoryUsage(percentUsed);
66
- if (percentUsed >= 90) this.handleExtremeMemoryUsage(usedMb, percentUsed);
67
- return false;
68
- }
69
-
70
- handleHighMemoryUsage(percentUsed) {
71
- const newBatchSize = Math.floor(this.batchSize / 2);
72
- this.updateBatchSize(newBatchSize);
73
- this.writeProgress(
74
- `High memory usage (${percentUsed}%). Reducing batchSize to ${newBatchSize}`
75
- );
76
- }
77
-
78
- handleExtremeMemoryUsage(usedMb, percentUsed) {
79
- // Issue warning
80
- const name = `Warning: High memory usage`;
81
- const message = `Memory usage at ${usedMb} MB (${percentUsed}% of heap allocation for this process).`;
82
- // Set class instance flag to debounce future warnings
83
- this.highMemoryUsage = true;
84
- // Output warning
85
- console.log(
86
- chalk.white.bgRed(`\n${name}`),
87
- chalk.red(`\n${message}`),
88
- chalk.red(`${this.suggestions()}`)
89
- );
90
- // Reset flag in 30 seconds
91
- setTimeout(() => {
92
- this.highMemoryUsage = false;
93
- }, 30000);
94
- }
95
-
96
- setIndex(options) {
97
- // Set Algolia index
98
- this.client = algolia(options.appId, options.apiKey);
99
- this.index = this.client.initIndex(options.indexName);
100
- }
101
-
102
- setTransformations(options) {
103
- try {
104
- // Set JSON record transformations
105
- const transformations = options.transformations
106
- ? require(this.normalizePath(options.transformations))
107
- : null;
108
- // Validate transformations function input param
109
- const valid = transformations && typeof transformations === 'function';
110
- // Assign our transformations function using provided custom transformations file if exists
111
- this.formatRecord = valid ? transformations : this.defaultTransformations;
112
- } catch (e) {
113
- throw e;
114
- }
115
- }
116
-
117
- setCsvOptions(options) {
118
- try {
119
- this.csvOptions = options.csvToJsonParams
120
- ? JSON.parse(options.csvToJsonParams)
121
- : null;
122
- if (!this.csvOptions) return;
123
- const csvToJsonRegexPropertyList = ['includeColumns', 'ignoreColumns'];
124
- csvToJsonRegexPropertyList.forEach(prop => {
125
- if (this.csvOptions.hasOwnProperty(prop)) {
126
- this.csvOptions[prop] = regexParser(this.csvOptions[prop]);
127
- }
128
- });
129
- } catch (e) {
130
- throw e;
131
- }
132
- }
133
-
134
- conditionallyParseCsv(isCsv) {
135
- // Return the appropriate writestream for piping depending on filetype
136
- return isCsv
137
- ? csv(this.csvOptions) // Convert from CSV to JSON
138
- : through(); // Do nothing
139
- }
140
-
141
- async setBatchSize(options) {
142
- try {
143
- // If user provided batchSize, use and exit early
144
- // Otherwise calculate and set optimal batch size
145
- if (options.objectsPerBatch !== null) {
146
- this.batchSize = options.objectsPerBatch;
147
- return;
148
- }
149
- // Test files to estimate optimal batch size
150
- const estimatedBatchSize = await this.estimateBatchSize();
151
- // Test network upload speed
152
- const uploadSpeedMb = await this.getNetworkSpeed();
153
- // Calculate optimal batch size
154
- this.writeProgress('Calculating optimal batch size...');
155
- let batchSize;
156
- // Reconcile batch size with network speed
157
- if (uploadSpeedMb >= this.desiredBatchSizeMb)
158
- batchSize = Math.floor(estimatedBatchSize);
159
- else
160
- batchSize = Math.floor(
161
- (uploadSpeedMb / this.desiredBatchSizeMb) * estimatedBatchSize
162
- );
163
- // Ensure minimum batch size is enforced
164
- batchSize = Math.max(this.minBatchSize, batchSize);
165
- console.log(chalk.blue(`\nOptimal batch size: ${batchSize}`));
166
- // Set batch size
167
- this.batchSize = batchSize;
168
- } catch (e) {
169
- throw e;
170
- }
171
- }
172
-
173
- estimateBatchSize() {
174
- // Read file, estimate average record size, estimate batch size
175
- // Return estimated batch size divided by maxConcurrency
176
- return new Promise((resolve, reject) => {
177
- try {
178
- const filename = this.filenames[0];
179
- const file = `${this.directory}/${filename}`;
180
- const isCsv = filename.split('.').pop() === 'csv';
181
- const fileStream = fs.createReadStream(file, {
182
- autoclose: true,
183
- flags: 'r',
184
- });
185
- this.writeProgress(`Estimating data size...`);
186
- const jsonStreamOption = isCsv ? null : '*';
187
- fileStream
188
- .pipe(this.conditionallyParseCsv(isCsv))
189
- .pipe(JSONStream.parse(jsonStreamOption))
190
- .pipe(transform(this.formatRecord))
191
- .pipe(new Batch({ size: 10000 }))
192
- .pipe(
193
- through(data => {
194
- const count = data.length;
195
- const string = JSON.stringify(data);
196
- const batchSizeMb = this.getStringSizeMb(string);
197
- const avgRecordSizeMb = batchSizeMb / count;
198
- const avgRecordSizeKb = Math.ceil(avgRecordSizeMb * 1000);
199
- const roughBatchSize = this.desiredBatchSizeMb / avgRecordSizeMb;
200
- const estimatedBatchSize = Math.floor(
201
- roughBatchSize / this.maxConcurrency
202
- );
203
- console.log(
204
- chalk.blue(`\nAverage record size: ${avgRecordSizeKb} Kb`)
205
- );
206
- fileStream.destroy();
207
- resolve(estimatedBatchSize);
208
- })
209
- );
210
- } catch (e) {
211
- reject(e);
212
- }
213
- });
214
- }
215
-
216
- updateBatchSize(newSize) {
217
- this.batchSize = newSize;
218
- }
219
-
220
- getBatchStream() {
221
- return new Batch({ size: this.batchSize });
222
- }
223
-
224
- async importToAlgolia(data) {
225
- // Method to index batches of records in Algolia
226
- try {
227
- await this.index.addObjects(data);
228
- this.importCount += data.length;
229
- this.writeProgress(`Records indexed: ${this.importCount}`);
230
- } catch (e) {
231
- let message = e.message;
232
- let addendum = e.stack;
233
- if (e.name === 'AlgoliaSearchRequestTimeoutError') {
234
- message = `You may be attempting to import batches too large for the network connection.`;
235
- addendum = this.suggestions();
236
- this.retryImport(data);
237
- }
238
- console.log(
239
- chalk.white.bgRed(`\nImport error: ${e.name}`),
240
- chalk.red(`\n${message}`),
241
- chalk.red(addendum)
242
- );
243
- throw e;
244
- }
245
- }
246
-
247
- retryImport(data) {
248
- // Algolia import retry strategy
249
- try {
250
- this.retryCount++;
251
- console.log(`\n(${this.retryCount}) Retrying batch...`);
252
- const importedBatchCount = Math.floor(this.importCount / this.batchSize);
253
- const retryLimit =
254
- this.retryCount > 15 && this.retryCount > importedBatchCount / 2;
255
- if (retryLimit) {
256
- console.log(
257
- chalk.white.bgRed(`\nError: Failure to index data`),
258
- chalk.red(`\nRetry limit reached.`),
259
- chalk.red(this.suggestions())
260
- );
261
- return;
262
- }
263
- // Split data in half
264
- const middle = Math.floor(data.length / 2);
265
- const firstHalf = data.splice(0, middle);
266
- // Reduce batchsize
267
- if (this.batchSize > middle) this.updateBatchSize(middle);
268
- // Push each half of data into import queue
269
- this.queue.push([firstHalf]);
270
- this.queue.push([data]);
271
- } catch (e) {
272
- console.error('Retry error:', e);
273
- throw e;
274
- }
275
- }
276
-
277
- indexFiles(filenames) {
278
- // Recursive method that iterates through an array of filenames, opens a read stream for each file
279
- // then pipes the read stream through a series of transformations (parse CSV/JSON objects, transform
280
- // them, batch them, index them in Algolia) while imposing a queue so that only so many
281
- // indexing threads will be run in parallel
282
- if (filenames.length <= 0) {
283
- console.log('\nDone reading files');
284
- return;
285
- }
286
- // Start new file read stream
287
- // Note: filenames is a reference to the mutable class instance variable this.filenames
288
- const filename = filenames.pop();
289
- const file = `${this.directory}/${filename}`;
290
- const isCsv = filename.split('.').pop() === 'csv';
291
- const fileStream = fs.createReadStream(file, {
292
- autoclose: true,
293
- flags: 'r',
294
- });
295
-
296
- fileStream.on('data', () => {
297
- if (this.queue.length() >= this.maxConcurrency) {
298
- // If async upload queue is full, pause reading from file stream
299
- fileStream.pause();
300
- }
301
- });
302
-
303
- fileStream.on('end', () => {
304
- // File complete, process next file
305
- this.indexFiles(filenames);
306
- });
307
-
308
- // Once the async upload queue is drained, resume reading from file stream
309
- this.queue.drain = () => {
310
- fileStream.resume();
311
- };
312
-
313
- // Handle parsing, transforming, batching, and indexing JSON and CSV files
314
- console.log(`\nImporting [${filename}]`);
315
- const jsonStreamOption = isCsv ? null : '*';
316
- fileStream
317
- .pipe(this.conditionallyParseCsv(isCsv, filename))
318
- .pipe(JSONStream.parse(jsonStreamOption))
319
- .pipe(transform(this.formatRecord))
320
- .pipe(this.getBatchStream())
321
- .pipe(
322
- through(data => {
323
- this.checkMemoryUsage();
324
- this.queue.push([data]);
325
- })
326
- );
327
- }
328
-
329
- async start(program) {
330
- // Script reads JSON or CSV file, or directory of such files, optionally applies
331
- // transformations, then batches and indexes the data in Algolia.
332
-
333
- // Validate command; if invalid display help text and exit
334
- this.validate(program, this.message, this.params);
335
-
336
- // Config params
337
- const options = {
338
- sourceFilepath: program.sourcefilepath,
339
- appId: program.algoliaappid,
340
- apiKey: program.algoliaapikey,
341
- indexName: program.algoliaindexname,
342
- objectsPerBatch: program.batchsize || null,
343
- transformations: program.transformationfilepath || null,
344
- maxConcurrency: program.maxconcurrency || 2,
345
- csvToJsonParams: program.params || null,
346
- };
347
- // Configure Algolia (this.client, this.index)
348
- this.setIndex(options);
349
- // Configure source paths (this.directory, this.filenames)
350
- this.setSource(options);
351
- // Configure transformations (this.formatRecord)
352
- this.setTransformations(options);
353
- // Configure optional csvtojson params (this.csvOptions)
354
- this.setCsvOptions(options);
355
- // Configure data upload parameters
356
- this.maxConcurrency = options.maxConcurrency;
357
- // Theoretically desirable batch size in MB
358
- this.desiredBatchSizeMb = 10;
359
- // Minimum batch size
360
- this.minBatchSize = 100;
361
- // Configure number of records to index per batch (this.batchSize, this.batch)
362
- await this.setBatchSize(options);
363
- // Assign dangerous memory usage flag
364
- this.highMemoryUsage = false;
365
- // Assign import count
366
- this.importCount = 0;
367
- // Assign retry count
368
- this.retryCount = 0;
369
- // Assign async queue
370
- this.queue = async.queue(this.importToAlgolia, this.maxConcurrency);
371
-
372
- // Execute import
373
- console.log(chalk.bgGreen.white('Starting import...'));
374
- return this.indexFiles(this.filenames);
375
- }
376
- }
377
-
378
- const importScript = new ImportScript();
379
- module.exports = importScript;
@@ -1,60 +0,0 @@
1
- const inquirer = require('inquirer');
2
-
3
- class Interactive {
4
- parseCommandNames(commandList, ownName) {
5
- const names = commandList.map(command => command._name);
6
- // Remove current command name and default command
7
- const commandNames = names.filter(name => name !== ownName && name !== '*');
8
- return commandNames;
9
- }
10
-
11
- getCommandQuestion(commandNames) {
12
- return {
13
- type: 'list',
14
- name: 'commandChoice',
15
- message: 'Select the command to run',
16
- choices: commandNames,
17
- };
18
- }
19
-
20
- getArgumentQuestions(validArguments) {
21
- return validArguments.map(argument => ({
22
- type: argument.description.includes('key') ? 'password' : 'input',
23
- name: argument.long.substring(2),
24
- message: `${argument.long} | ${argument.description}`,
25
- }));
26
- }
27
-
28
- async start(program) {
29
- try {
30
- const commands = require('../commands.js');
31
- const ownName = program._name;
32
- const commandList = program.parent.commands;
33
- // Get list of valid commands
34
- const commandNames = this.parseCommandNames(commandList, ownName);
35
- const commandQuestion = this.getCommandQuestion(commandNames);
36
- // Prompt user to select a command
37
- const commandResponse = await inquirer.prompt(commandQuestion);
38
- // Prepare subsequent questions
39
- const selectedCommand = commandList.find(
40
- command => command._name === commandResponse.commandChoice
41
- );
42
- const validArguments = selectedCommand.options;
43
- const argumentQuestions = this.getArgumentQuestions(validArguments);
44
- // Prompt user to input command arguments
45
- const argumentsResponse = await inquirer.prompt(argumentQuestions);
46
- // Pass arguments to program
47
- const argumentsList = Object.keys(argumentsResponse);
48
- argumentsList.forEach(arg => {
49
- if (argumentsResponse[arg] !== '')
50
- program[arg] = argumentsResponse[arg]; // eslint-disable-line no-param-reassign
51
- });
52
- // Execute selected command
53
- commands[selectedCommand._name].start(program);
54
- } catch (e) {
55
- throw e;
56
- }
57
- }
58
- }
59
-
60
- module.exports = new Interactive();
@@ -1,68 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const algolia = require('algoliasearch');
4
- const Base = require('./Base.js');
5
-
6
- class SearchScript extends Base {
7
- constructor() {
8
- super();
9
- // Bind class methods
10
- this.start = this.start.bind(this);
11
- this.parseSearchOptions = this.parseSearchOptions.bind(this);
12
- this.writeOutput = this.writeOutput.bind(this);
13
- // Define validation constants
14
- this.message =
15
- '\nExample: $ algolia search -a algoliaappid -k algoliaapikey -n algoliaindexname -q query -p searchparams -o outputpath\n\n';
16
- this.params = ['algoliaappid', 'algoliaapikey', 'algoliaindexname'];
17
- }
18
-
19
- parseSearchOptions(params) {
20
- return params === null ? {} : JSON.parse(params);
21
- }
22
-
23
- async writeOutput(outputFilepath, content) {
24
- const defaultFilepath = path.resolve(process.cwd(), 'search-results.json');
25
- const filepath = this.normalizePath(outputFilepath);
26
- const dir = path.dirname(filepath);
27
- if (!fs.lstatSync(dir).isDirectory()) {
28
- throw new Error(
29
- `Output path must target valid directory. Eg. ${defaultFilepath}`
30
- );
31
- } else {
32
- await fs.writeFileSync(filepath, content);
33
- }
34
- }
35
-
36
- async start(program) {
37
- try {
38
- // Validate command; if invalid display help text and exit
39
- this.validate(program, this.message, this.params);
40
-
41
- // Config params
42
- const appId = program.algoliaappid;
43
- const apiKey = program.algoliaapikey;
44
- const indexName = program.algoliaindexname;
45
- const query = program.query || '';
46
- const params = program.params || null;
47
- const outputPath = program.outputpath || null;
48
-
49
- // Get options
50
- const options = this.parseSearchOptions(params);
51
-
52
- // Instantiate Algolia index
53
- const client = algolia(appId, apiKey);
54
- const index = client.initIndex(indexName);
55
- // Get index settings
56
- const result = await index.search(query, options);
57
- const output = JSON.stringify(result);
58
- return outputPath === null
59
- ? console.log(output)
60
- : await this.writeOutput(outputPath, output);
61
- } catch (e) {
62
- throw e;
63
- }
64
- }
65
- }
66
-
67
- const searchScript = new SearchScript();
68
- module.exports = searchScript;