@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.
- package/README.md +42 -0
- package/bin/run.js +26 -0
- package/package.json +26 -78
- package/commands/AddRules.js +0 -72
- package/commands/AddSynonyms.js +0 -89
- package/commands/Base.js +0 -97
- package/commands/DeleteIndicesPattern.js +0 -104
- package/commands/Export.js +0 -117
- package/commands/ExportRules.js +0 -61
- package/commands/ExportSynonyms.js +0 -61
- package/commands/GetSettings.js +0 -38
- package/commands/Import.js +0 -379
- package/commands/Interactive.js +0 -60
- package/commands/Search.js +0 -68
- package/commands/SetSettings.js +0 -72
- package/commands/TransferIndex.js +0 -126
- package/commands/TransferIndexConfig.js +0 -108
- package/commands/TransformLines.js +0 -136
- package/commands.js +0 -16
- package/index.js +0 -373
- package/readme.md +0 -656
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Algolia CLI
|
|
2
|
+
|
|
3
|
+
The official Algolia CLI lets you manage your Algolia resources — indices, records, API keys, and synonyms — directly from the command line.
|
|
4
|
+
|
|
5
|
+
> This package installs a prebuilt Go binary. The npm wrapper still requires Node.js to launch the installed command.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install -g @algolia/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run without installing:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx @algolia/cli --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
algolia --help
|
|
23
|
+
algolia search --index my-index --query "foo"
|
|
24
|
+
algolia indices list
|
|
25
|
+
algolia apikeys list
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
Full documentation: [algolia.com/doc/tools/cli](https://algolia.com/doc/tools/cli/)
|
|
31
|
+
|
|
32
|
+
## Supported platforms
|
|
33
|
+
|
|
34
|
+
| OS | x64 | arm64 |
|
|
35
|
+
|---------|-----|-------|
|
|
36
|
+
| macOS | ✓ | ✓ |
|
|
37
|
+
| Linux | ✓ | ✓ |
|
|
38
|
+
| Windows | ✓ | ✓ |
|
|
39
|
+
|
|
40
|
+
## Issues
|
|
41
|
+
|
|
42
|
+
[github.com/algolia/cli/issues](https://github.com/algolia/cli/issues)
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { execFileSync } = require('child_process');
|
|
5
|
+
|
|
6
|
+
let binPath;
|
|
7
|
+
switch (`${process.platform}-${process.arch}`) {
|
|
8
|
+
case 'darwin-x64': ({ binPath } = require('@algolia/cli-darwin-x64')); break;
|
|
9
|
+
case 'darwin-arm64': ({ binPath } = require('@algolia/cli-darwin-arm64')); break;
|
|
10
|
+
case 'linux-x64': ({ binPath } = require('@algolia/cli-linux-x64')); break;
|
|
11
|
+
case 'linux-arm64': ({ binPath } = require('@algolia/cli-linux-arm64')); break;
|
|
12
|
+
case 'win32-x64': ({ binPath } = require('@algolia/cli-win32-x64')); break;
|
|
13
|
+
case 'win32-arm64': ({ binPath } = require('@algolia/cli-win32-arm64')); break;
|
|
14
|
+
default:
|
|
15
|
+
console.error(
|
|
16
|
+
`algolia: unsupported platform ${process.platform}/${process.arch}\n` +
|
|
17
|
+
`Install the appropriate platform package manually: npm install @algolia/cli-${process.platform}-${process.arch}`
|
|
18
|
+
);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
execFileSync(binPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
24
|
+
} catch (e) {
|
|
25
|
+
process.exit(e.status ?? 1);
|
|
26
|
+
}
|
package/package.json
CHANGED
|
@@ -1,90 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@algolia/cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"license": "ISC",
|
|
6
|
-
"author": "Algolia, Inc. (https://www.algolia.com)",
|
|
7
|
-
"main": "index.js",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git://github.com/algolia/algolia-cli.git"
|
|
11
|
-
},
|
|
3
|
+
"version": "5.10.0",
|
|
4
|
+
"description": "The official Algolia CLI — manage indices, records, API keys, and synonyms from the command line",
|
|
12
5
|
"bin": {
|
|
13
|
-
"algolia": "
|
|
14
|
-
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"test": "jest --runInBand",
|
|
17
|
-
"test:unit": "jest commands/",
|
|
18
|
-
"test:unit:watch": "jest --watch commands/",
|
|
19
|
-
"test:integration": "jest --runInBand tests/integration/",
|
|
20
|
-
"lint": "eslint .",
|
|
21
|
-
"lint:fix": "npm run lint -- --fix"
|
|
22
|
-
},
|
|
23
|
-
"engines": {
|
|
24
|
-
"node": ">=8.9.1",
|
|
25
|
-
"yarn": ">=1.10.1"
|
|
6
|
+
"algolia": "bin/run.js"
|
|
26
7
|
},
|
|
27
8
|
"files": [
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"index.js",
|
|
31
|
-
"!commands/*.test.js"
|
|
9
|
+
"bin/run.js",
|
|
10
|
+
"README.md"
|
|
32
11
|
],
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
12
|
+
"optionalDependencies": {
|
|
13
|
+
"@algolia/cli-darwin-x64": "5.10.0",
|
|
14
|
+
"@algolia/cli-darwin-arm64": "5.10.0",
|
|
15
|
+
"@algolia/cli-linux-x64": "5.10.0",
|
|
16
|
+
"@algolia/cli-linux-arm64": "5.10.0",
|
|
17
|
+
"@algolia/cli-win32-x64": "5.10.0",
|
|
18
|
+
"@algolia/cli-win32-arm64": "5.10.0"
|
|
37
19
|
},
|
|
38
20
|
"keywords": [
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"import",
|
|
47
|
-
"index",
|
|
48
|
-
"solutions",
|
|
49
|
-
"se",
|
|
50
|
-
"cli"
|
|
21
|
+
"algolia",
|
|
22
|
+
"cli",
|
|
23
|
+
"search",
|
|
24
|
+
"indices",
|
|
25
|
+
"records",
|
|
26
|
+
"api-keys",
|
|
27
|
+
"synonyms"
|
|
51
28
|
],
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"batch-stream": "^0.1.3",
|
|
57
|
-
"chalk": "^2.4.1",
|
|
58
|
-
"commander": "^2.19.0",
|
|
59
|
-
"csvtojson": "^2.0.8",
|
|
60
|
-
"inquirer": "^6.2.2",
|
|
61
|
-
"regex-parser": "^2.2.10",
|
|
62
|
-
"speedtest-net": "^1.5.1",
|
|
63
|
-
"stream-transform": "^1.0.7",
|
|
64
|
-
"through": "^2.3.8"
|
|
65
|
-
},
|
|
66
|
-
"devDependencies": {
|
|
67
|
-
"babel-eslint": "^10.0.1",
|
|
68
|
-
"babel-jest": "^23.6.0",
|
|
69
|
-
"dotenv": "^6.2.0",
|
|
70
|
-
"eslint": "^5.9.0",
|
|
71
|
-
"eslint-config-algolia": "^13.2.3",
|
|
72
|
-
"eslint-config-prettier": "^3.3.0",
|
|
73
|
-
"eslint-plugin-import": "^2.14.0",
|
|
74
|
-
"eslint-plugin-jest": "^22.1.2",
|
|
75
|
-
"eslint-plugin-prettier": "^3.0.0",
|
|
76
|
-
"jest": "^23.6.0",
|
|
77
|
-
"prettier": "^1.15.3",
|
|
78
|
-
"randomatic": "^3.1.1",
|
|
79
|
-
"rimraf": "^2.6.2",
|
|
80
|
-
"striptags": "^3.1.1"
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"homepage": "https://algolia.com/doc/tools/cli/",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/algolia/cli/issues"
|
|
81
33
|
},
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"testURL": "http://localhost/",
|
|
86
|
-
"setupFiles": [
|
|
87
|
-
"./tests/config.js"
|
|
88
|
-
]
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/algolia/cli.git"
|
|
89
37
|
}
|
|
90
38
|
}
|
package/commands/AddRules.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const algolia = require('algoliasearch');
|
|
3
|
-
const Base = require('./Base.js');
|
|
4
|
-
|
|
5
|
-
class AddRulesScript extends Base {
|
|
6
|
-
constructor() {
|
|
7
|
-
super();
|
|
8
|
-
// Bind class methods
|
|
9
|
-
this.getSource = this.getSource.bind(this);
|
|
10
|
-
this.parseBatchRulesOptions = this.parseBatchRulesOptions.bind(this);
|
|
11
|
-
this.start = this.start.bind(this);
|
|
12
|
-
// Define validation constants
|
|
13
|
-
this.message =
|
|
14
|
-
'\nExample: $ algolia addrules -a algoliaappid -k algoliaapikey -n algoliaindexname -s sourcefilepath -p batchRulesParams\n\n';
|
|
15
|
-
this.params = [
|
|
16
|
-
'algoliaappid',
|
|
17
|
-
'algoliaapikey',
|
|
18
|
-
'algoliaindexname',
|
|
19
|
-
'sourcefilepath',
|
|
20
|
-
];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
getSource(path) {
|
|
24
|
-
const filepath = this.normalizePath(path);
|
|
25
|
-
if (!fs.lstatSync(filepath).isFile())
|
|
26
|
-
throw new Error('Source filepath must target valid rules file.');
|
|
27
|
-
return filepath;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
parseBatchRulesOptions(params) {
|
|
31
|
-
try {
|
|
32
|
-
const options = { forwardToReplicas: false, clearExistingRules: false };
|
|
33
|
-
if (params === null) return options;
|
|
34
|
-
else return JSON.parse(params);
|
|
35
|
-
} catch (e) {
|
|
36
|
-
throw e;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async start(program) {
|
|
41
|
-
try {
|
|
42
|
-
// Validate command; if invalid display help text and exit
|
|
43
|
-
this.validate(program, this.message, this.params);
|
|
44
|
-
|
|
45
|
-
// Config params
|
|
46
|
-
const appId = program.algoliaappid;
|
|
47
|
-
const apiKey = program.algoliaapikey;
|
|
48
|
-
const indexName = program.algoliaindexname;
|
|
49
|
-
const sourcefilepath = program.sourcefilepath;
|
|
50
|
-
const params = program.params || null;
|
|
51
|
-
|
|
52
|
-
// Get rules
|
|
53
|
-
const rulesPath = this.getSource(sourcefilepath);
|
|
54
|
-
const rulesFile = await fs.readFileSync(rulesPath);
|
|
55
|
-
const rules = JSON.parse(rulesFile);
|
|
56
|
-
// Get options
|
|
57
|
-
const batchRulesOptions = this.parseBatchRulesOptions(params);
|
|
58
|
-
|
|
59
|
-
// Instantiate Algolia index
|
|
60
|
-
const client = algolia(appId, apiKey);
|
|
61
|
-
const index = client.initIndex(indexName);
|
|
62
|
-
// Add rules
|
|
63
|
-
const result = await index.batchRules(rules, batchRulesOptions);
|
|
64
|
-
return console.log(result);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
throw e;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const addRulesScript = new AddRulesScript();
|
|
72
|
-
module.exports = addRulesScript;
|
package/commands/AddSynonyms.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const algolia = require('algoliasearch');
|
|
3
|
-
const Base = require('./Base.js');
|
|
4
|
-
|
|
5
|
-
class AddSynonymsScript extends Base {
|
|
6
|
-
constructor() {
|
|
7
|
-
super();
|
|
8
|
-
// Bind class methods
|
|
9
|
-
this.getSource = this.getSource.bind(this);
|
|
10
|
-
this.parseBatchSynonymsOptions = this.parseBatchSynonymsOptions.bind(this);
|
|
11
|
-
this.convertCsvToJson = this.convertCsvToJson.bind(this);
|
|
12
|
-
this.start = this.start.bind(this);
|
|
13
|
-
// Define validation constants
|
|
14
|
-
this.message =
|
|
15
|
-
'\nExample: $ algolia addsynonyms -a algoliaappid -k algoliaapikey -n algoliaindexname -s sourcefilepath -p batchSynonymsParams\n\n';
|
|
16
|
-
this.params = [
|
|
17
|
-
'algoliaappid',
|
|
18
|
-
'algoliaapikey',
|
|
19
|
-
'algoliaindexname',
|
|
20
|
-
'sourcefilepath',
|
|
21
|
-
];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
getSource(path) {
|
|
25
|
-
const filepath = this.normalizePath(path);
|
|
26
|
-
if (!fs.lstatSync(filepath).isFile())
|
|
27
|
-
throw new Error('Source filepath must target valid synonyms file.');
|
|
28
|
-
return filepath;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
parseBatchSynonymsOptions(params) {
|
|
32
|
-
try {
|
|
33
|
-
const options = {
|
|
34
|
-
forwardToReplicas: false,
|
|
35
|
-
clearExistingSynonyms: false,
|
|
36
|
-
};
|
|
37
|
-
if (params === null) return options;
|
|
38
|
-
else return JSON.parse(params);
|
|
39
|
-
} catch (e) {
|
|
40
|
-
throw e;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
convertCsvToJson(synonymFile, filepath) {
|
|
45
|
-
const synonyms = synonymFile.toString().split('\n');
|
|
46
|
-
return synonyms.map((line, num) => ({
|
|
47
|
-
type: 'synonym',
|
|
48
|
-
objectID: `${filepath}-${num}`,
|
|
49
|
-
synonyms: line.split(','),
|
|
50
|
-
}));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async start(program) {
|
|
54
|
-
try {
|
|
55
|
-
// Validate command; if invalid display help text and exit
|
|
56
|
-
this.validate(program, this.message, this.params);
|
|
57
|
-
|
|
58
|
-
// Config params
|
|
59
|
-
const appId = program.algoliaappid;
|
|
60
|
-
const apiKey = program.algoliaapikey;
|
|
61
|
-
const indexName = program.algoliaindexname;
|
|
62
|
-
const sourcefilepath = program.sourcefilepath;
|
|
63
|
-
const params = program.params || null;
|
|
64
|
-
const isCsv = sourcefilepath.split('.').pop() === 'csv';
|
|
65
|
-
|
|
66
|
-
// Get synonyms
|
|
67
|
-
const synonymsPath = this.getSource(sourcefilepath);
|
|
68
|
-
const synonymsFile = await fs.readFileSync(synonymsPath);
|
|
69
|
-
const synonyms = isCsv
|
|
70
|
-
? this.convertCsvToJson(synonymsFile, sourcefilepath)
|
|
71
|
-
: JSON.parse(synonymsFile);
|
|
72
|
-
|
|
73
|
-
// Get options
|
|
74
|
-
const batchSynonymsOptions = this.parseBatchSynonymsOptions(params);
|
|
75
|
-
|
|
76
|
-
// Instantiate Algolia index
|
|
77
|
-
const client = algolia(appId, apiKey);
|
|
78
|
-
const index = client.initIndex(indexName);
|
|
79
|
-
// Add rules
|
|
80
|
-
const result = await index.batchSynonyms(synonyms, batchSynonymsOptions);
|
|
81
|
-
return console.log(result);
|
|
82
|
-
} catch (e) {
|
|
83
|
-
throw e;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const addSynonymsScript = new AddSynonymsScript();
|
|
89
|
-
module.exports = addSynonymsScript;
|
package/commands/Base.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
const os = require('os');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const readLine = require('readline');
|
|
5
|
-
const chalk = require('chalk');
|
|
6
|
-
const speedTest = require('speedtest-net');
|
|
7
|
-
|
|
8
|
-
class Base {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.maxHeapMb = process.arch.includes('64') ? 1024 : 512;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
validate(program, message, params) {
|
|
14
|
-
let flag = false;
|
|
15
|
-
let output = message;
|
|
16
|
-
params.forEach(param => {
|
|
17
|
-
if (!program[param]) {
|
|
18
|
-
output += chalk.red(`Must specify ${param}\n`);
|
|
19
|
-
flag = true;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
if (flag) return program.help(h => h + output);
|
|
23
|
-
else return { flag, output };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
writeProgress(message) {
|
|
27
|
-
readLine.clearLine(process.stdout, 0);
|
|
28
|
-
readLine.cursorTo(process.stdout, 0);
|
|
29
|
-
process.stdout.write(message);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
normalizePath(input) {
|
|
33
|
-
// Convert path input param to valid system absolute path
|
|
34
|
-
// Path is absolute, originating from system root
|
|
35
|
-
if (path.isAbsolute(input)) return input;
|
|
36
|
-
// Path is relative to user's home directory
|
|
37
|
-
if (input[0] === '~') return path.join(os.homedir(), input.substr(1));
|
|
38
|
-
// Path is relative to current directory
|
|
39
|
-
return path.resolve(process.cwd(), input);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
setSource(options) {
|
|
43
|
-
// Set source directory and filenames array
|
|
44
|
-
// Used to process path inputs that may either be a single file or a directory of files
|
|
45
|
-
const source = this.normalizePath(options.sourceFilepath);
|
|
46
|
-
if (fs.lstatSync(source).isDirectory()) {
|
|
47
|
-
this.directory = source;
|
|
48
|
-
this.filenames = fs.readdirSync(source);
|
|
49
|
-
} else if (fs.lstatSync(source).isFile()) {
|
|
50
|
-
this.directory = path.parse(source).dir;
|
|
51
|
-
this.filenames = [path.parse(source).base];
|
|
52
|
-
} else {
|
|
53
|
-
throw new Error('Invalid sourcefilepath param');
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
getMemoryUsage() {
|
|
58
|
-
const used = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
59
|
-
const usedMb = Math.round(used * 100) / 100;
|
|
60
|
-
const percentUsed = Math.floor((usedMb / this.maxHeapMb) * 100);
|
|
61
|
-
return { usedMb, percentUsed };
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
getStringSizeMb(string) {
|
|
65
|
-
const bytes = Buffer.byteLength(string, 'utf8');
|
|
66
|
-
const mb = bytes / 1024 / 1024;
|
|
67
|
-
return Math.ceil(mb);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getNetworkSpeed() {
|
|
71
|
-
return new Promise((resolve, reject) => {
|
|
72
|
-
this.writeProgress('Estimating network speed...');
|
|
73
|
-
const test = speedTest({ maxTime: 5000 });
|
|
74
|
-
let downloadSpeedMb = null;
|
|
75
|
-
let uploadSpeedMb = null;
|
|
76
|
-
test.on('error', e => {
|
|
77
|
-
console.log(chalk.white.bgRed('Speed test error'), chalk.red(e));
|
|
78
|
-
reject(e);
|
|
79
|
-
});
|
|
80
|
-
test.on('downloadspeed', speed => {
|
|
81
|
-
downloadSpeedMb = ((speed * 125) / 1000).toFixed(2);
|
|
82
|
-
});
|
|
83
|
-
test.on('uploadspeed', speed => {
|
|
84
|
-
uploadSpeedMb = ((speed * 125) / 1000).toFixed(2);
|
|
85
|
-
});
|
|
86
|
-
test.on('done', () => {
|
|
87
|
-
console.log(
|
|
88
|
-
chalk.blue(`\nDownload: ${downloadSpeedMb} MB/s`),
|
|
89
|
-
chalk.blue(`\nUpload: ${uploadSpeedMb} MB/s`)
|
|
90
|
-
);
|
|
91
|
-
resolve(uploadSpeedMb);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
module.exports = Base;
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
const algolia = require('algoliasearch');
|
|
2
|
-
const Base = require('./Base.js');
|
|
3
|
-
|
|
4
|
-
class DeleteIndicesPatternScript extends Base {
|
|
5
|
-
constructor() {
|
|
6
|
-
super();
|
|
7
|
-
// Define validation constants
|
|
8
|
-
this.message =
|
|
9
|
-
"\nUsage: $ algolia deleteindices -a algoliaappid -k algoliaapikey -r 'regexp for filtering' -x\n\n";
|
|
10
|
-
this.params = ['algoliaappid', 'algoliaapikey', 'regexp', 'dryrun'];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
removeReplicas({ indices, regexp, dryRun }) {
|
|
14
|
-
return Promise.all(
|
|
15
|
-
indices.map(async ({ name: indexName }) => {
|
|
16
|
-
const index = await this.client.initIndex(indexName);
|
|
17
|
-
const indexSettings = await index.getSettings();
|
|
18
|
-
const replicas = indexSettings.slaves || indexSettings.replicas;
|
|
19
|
-
if (replicas !== undefined && replicas.length > 0) {
|
|
20
|
-
const newReplicas = replicas.filter(
|
|
21
|
-
replicaIndexName => regexp.test(replicaIndexName) === false
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
if (replicas.length !== newReplicas.length) {
|
|
25
|
-
if (dryRun === false) {
|
|
26
|
-
const { taskID } = await index.setSettings({
|
|
27
|
-
[indexSettings.slaves !== undefined
|
|
28
|
-
? 'slaves'
|
|
29
|
-
: 'replicas']: newReplicas,
|
|
30
|
-
});
|
|
31
|
-
await index.waitTask(taskID);
|
|
32
|
-
} else {
|
|
33
|
-
console.log(
|
|
34
|
-
`[DRY RUN] Replicas change on index ${indexName}, \n- before: ${replicas.join(
|
|
35
|
-
','
|
|
36
|
-
)}\n- after: ${newReplicas.join(',')}`
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return false;
|
|
43
|
-
})
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
deleteIndices({ indices, regexp, dryRun }) {
|
|
48
|
-
let deletedIndices = 0;
|
|
49
|
-
return Promise.all(
|
|
50
|
-
indices
|
|
51
|
-
.filter(({ name: indexName }) => regexp.test(indexName) === true)
|
|
52
|
-
.map(async ({ name: indexName }) => {
|
|
53
|
-
deletedIndices++;
|
|
54
|
-
|
|
55
|
-
if (dryRun === false) {
|
|
56
|
-
this.writeProgress(`Deleted indices: ${deletedIndices}`);
|
|
57
|
-
const index = this.client.initIndex(indexName);
|
|
58
|
-
const { taskID } = await this.client.deleteIndex(indexName);
|
|
59
|
-
return index.waitTask(taskID);
|
|
60
|
-
} else {
|
|
61
|
-
console.log(`[DRY RUN] Delete index ${indexName}`);
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
).then(() => {
|
|
66
|
-
console.log('');
|
|
67
|
-
if (dryRun === false) {
|
|
68
|
-
console.log(`${deletedIndices} indices deleted`);
|
|
69
|
-
} else {
|
|
70
|
-
console.log(`[DRY RUN] ${deletedIndices} indices deleted`);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async deleteIndicesPattern(options) {
|
|
76
|
-
this.client = algolia(options.appId, options.apiKey);
|
|
77
|
-
const { items: indices } = await this.client.listIndexes();
|
|
78
|
-
const regexp = new RegExp(options.regexp);
|
|
79
|
-
await this.removeReplicas({ indices, regexp, dryRun: options.dryRun });
|
|
80
|
-
await this.deleteIndices({ indices, regexp, dryRun: options.dryRun });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
start(program) {
|
|
84
|
-
try {
|
|
85
|
-
// Validate command; if invalid display help text and exit
|
|
86
|
-
this.validate(program, this.message, this.params);
|
|
87
|
-
|
|
88
|
-
// Config params
|
|
89
|
-
const options = {
|
|
90
|
-
appId: program.algoliaappid,
|
|
91
|
-
apiKey: program.algoliaapikey,
|
|
92
|
-
regexp: program.regexp,
|
|
93
|
-
dryRun: program.dryrun !== undefined ? program.dryrun === 'true' : true,
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// Delete indices
|
|
97
|
-
return this.deleteIndicesPattern(options);
|
|
98
|
-
} catch (e) {
|
|
99
|
-
throw e;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
module.exports = new DeleteIndicesPatternScript();
|
package/commands/Export.js
DELETED
|
@@ -1,117 +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 ExportScript extends Base {
|
|
7
|
-
constructor() {
|
|
8
|
-
super();
|
|
9
|
-
// Bind class methods
|
|
10
|
-
this.getOutput = this.getOutput.bind(this);
|
|
11
|
-
this.parseParams = this.parseParams.bind(this);
|
|
12
|
-
this.writeFile = this.writeFile.bind(this);
|
|
13
|
-
this.exportData = this.exportData.bind(this);
|
|
14
|
-
this.start = this.start.bind(this);
|
|
15
|
-
// Define validation constants
|
|
16
|
-
this.message =
|
|
17
|
-
'\nExample: $ algolia export -a algoliaappid -k algoliaapikey -n algoliaindexname -o outputpath -p params\n\n';
|
|
18
|
-
this.params = ['algoliaappid', 'algoliaapikey', 'algoliaindexname'];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
getOutput(outputPath) {
|
|
22
|
-
// If no outputPath is provided, use directory from which command was invoked
|
|
23
|
-
const outputDir =
|
|
24
|
-
outputPath !== null ? this.normalizePath(outputPath) : process.cwd();
|
|
25
|
-
// Ensure outputPath is a directory
|
|
26
|
-
if (!fs.lstatSync(outputDir).isDirectory())
|
|
27
|
-
throw new Error('Output path must be a directory.');
|
|
28
|
-
return outputDir;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
parseParams(params) {
|
|
32
|
-
try {
|
|
33
|
-
if (params === null) return { hitsPerPage: 1000 };
|
|
34
|
-
return JSON.parse(params);
|
|
35
|
-
} catch (e) {
|
|
36
|
-
throw e;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
writeFile(hits, options, fileCount) {
|
|
41
|
-
const filename = `algolia-index-${options.indexName}-${fileCount}.json`;
|
|
42
|
-
const filePath = path.resolve(options.outputPath, filename);
|
|
43
|
-
fs.writeFileSync(filePath, JSON.stringify(hits));
|
|
44
|
-
return console.log(`\nDone writing ${filename}`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
exportData(options) {
|
|
48
|
-
return new Promise((resolve, reject) => {
|
|
49
|
-
// Instantiate Algolia index
|
|
50
|
-
const client = algolia(options.appId, options.apiKey);
|
|
51
|
-
const index = client.initIndex(options.indexName);
|
|
52
|
-
|
|
53
|
-
// Export index
|
|
54
|
-
const browse = index.browseAll('', options.params);
|
|
55
|
-
let hits = [];
|
|
56
|
-
let hitsCount = 0;
|
|
57
|
-
let fileCount = 0;
|
|
58
|
-
|
|
59
|
-
browse.on('result', result => {
|
|
60
|
-
// Push 1000 new hits to array
|
|
61
|
-
hits = hits.concat(result.hits);
|
|
62
|
-
hitsCount += result.hits.length;
|
|
63
|
-
this.writeProgress(`Records browsed: ${hitsCount}`);
|
|
64
|
-
if (hits.length >= 10000) {
|
|
65
|
-
// Write batch of 10,000 records to file
|
|
66
|
-
fileCount++;
|
|
67
|
-
this.writeFile(hits, options, fileCount);
|
|
68
|
-
// Clear array
|
|
69
|
-
hits = [];
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
browse.on('end', () => {
|
|
74
|
-
if (hits.length > 0) {
|
|
75
|
-
// Write remaining records to file
|
|
76
|
-
fileCount++;
|
|
77
|
-
this.writeFile(hits, options, fileCount);
|
|
78
|
-
}
|
|
79
|
-
return resolve(
|
|
80
|
-
`\nDone exporting index.\nSee your data here: ${options.outputPath}`
|
|
81
|
-
);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
browse.on('error', err => reject(err));
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async start(program) {
|
|
89
|
-
try {
|
|
90
|
-
// Validate command; if invalid display help text and exit
|
|
91
|
-
this.validate(program, this.message, this.params);
|
|
92
|
-
|
|
93
|
-
// Config params
|
|
94
|
-
const options = {
|
|
95
|
-
appId: program.algoliaappid,
|
|
96
|
-
apiKey: program.algoliaapikey,
|
|
97
|
-
indexName: program.algoliaindexname,
|
|
98
|
-
outputPath: program.outputpath || null,
|
|
99
|
-
params: program.params || null,
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// Configure and validate output path
|
|
103
|
-
options.outputPath = this.getOutput(options.outputPath);
|
|
104
|
-
// Configure browseAll params
|
|
105
|
-
options.params = this.parseParams(options.params);
|
|
106
|
-
|
|
107
|
-
// Export data
|
|
108
|
-
const result = await this.exportData(options);
|
|
109
|
-
return console.log(result);
|
|
110
|
-
} catch (e) {
|
|
111
|
-
throw e;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const exportScript = new ExportScript();
|
|
117
|
-
module.exports = exportScript;
|