apify-cli 0.15.0-beta.0 → 0.15.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/package.json +105 -105
- package/src/commands/create.js +23 -9
- package/src/commands/run.js +22 -17
- package/src/lib/utils.js +26 -1
- package/src/lib/version_check.js +2 -2
package/package.json
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
2
|
+
"name": "apify-cli",
|
|
3
|
+
"version": "0.15.0",
|
|
4
|
+
"description": "Apify command-line interface helps you create, develop, build and run Apify actors, and manage the Apify cloud platform.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "mocha --timeout 180000 --recursive",
|
|
8
|
+
"test-python": "mocha --timeout 180000 --recursive --grep '\\[python\\]'",
|
|
9
|
+
"lint": "eslint src test",
|
|
10
|
+
"lint:fix": "eslint src test --fix",
|
|
11
|
+
"commands-md": "npm run manifest && oclif-dev readme",
|
|
12
|
+
"prepare-release": "npm run commands-md && npm run prod-shrinkwrap",
|
|
13
|
+
"prod-shrinkwrap": "rm -rf node_modules && npm install --production && npm shrinkwrap",
|
|
14
|
+
"manifest": "rm -f oclif.manifest.json && oclif-dev manifest",
|
|
15
|
+
"postinstall": "node \"./src/bin/run\" check-version"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"src",
|
|
19
|
+
"oclif.manifest.json",
|
|
20
|
+
"index.js",
|
|
21
|
+
"package.json"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"apify": "./src/bin/run"
|
|
25
|
+
},
|
|
26
|
+
"contributors": [
|
|
27
|
+
"Jakub Drobník <jakub.drobnik@apify.com>",
|
|
28
|
+
"Jan Curn <jan@apify.com>"
|
|
29
|
+
],
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/apify/apify-cli.git"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"apify",
|
|
36
|
+
"client",
|
|
37
|
+
"node",
|
|
38
|
+
"command",
|
|
39
|
+
"line",
|
|
40
|
+
"bash"
|
|
41
|
+
],
|
|
42
|
+
"author": {
|
|
43
|
+
"name": "Apify",
|
|
44
|
+
"email": "support@apify.com",
|
|
45
|
+
"url": "https://www.apify.com"
|
|
46
|
+
},
|
|
47
|
+
"license": "Apache-2.0",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/apify/apify-cli/issues"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/apify/apify-cli#readme",
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=16.0.0"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@apify/actor-templates": "^0.1.3",
|
|
57
|
+
"@apify/consts": "^2.7.0",
|
|
58
|
+
"@apify/input_schema": "^3.3.0",
|
|
59
|
+
"@apify/utilities": "^2.2.3",
|
|
60
|
+
"@crawlee/memory-storage": "^3.0.3",
|
|
61
|
+
"@oclif/command": "^1.8.16",
|
|
62
|
+
"@oclif/config": "^1.18.3",
|
|
63
|
+
"@oclif/errors": "^1.3.5",
|
|
64
|
+
"@oclif/plugin-commands": "^2.1.0",
|
|
65
|
+
"@oclif/plugin-help": "^5.1.12",
|
|
66
|
+
"ajv": "^8.10.0",
|
|
67
|
+
"apify-client": "^2.2.0",
|
|
68
|
+
"archiver-promise": "^1.0.0",
|
|
69
|
+
"axios": "^0.21.1",
|
|
70
|
+
"chalk": "^4.1.2",
|
|
71
|
+
"computer-name": "^0.1.0",
|
|
72
|
+
"cors": "^2.8.5",
|
|
73
|
+
"detect-indent": "^6.1.0",
|
|
74
|
+
"express": "^4.18.2",
|
|
75
|
+
"globby": "^11.1.0",
|
|
76
|
+
"inquirer": "^7.3.3",
|
|
77
|
+
"is-online": "^10.0.0",
|
|
78
|
+
"istextorbinary": "^6.0.0",
|
|
79
|
+
"load-json-file": "^6.2.0",
|
|
80
|
+
"mime": "^2.6.0",
|
|
81
|
+
"open": "^8.4.0",
|
|
82
|
+
"ow": "^0.28.1",
|
|
83
|
+
"rimraf": "^3.0.2",
|
|
84
|
+
"semver": "^7.3.5",
|
|
85
|
+
"underscore": "^1.13.2",
|
|
86
|
+
"unzipper": "^0.10.11",
|
|
87
|
+
"write-json-file": "^4.3.0"
|
|
88
|
+
},
|
|
89
|
+
"devDependencies": {
|
|
90
|
+
"@apify/eslint-config": "^0.2.3",
|
|
91
|
+
"@oclif/dev-cli": "^1.26.0",
|
|
92
|
+
"@oclif/test": "^2.1.0",
|
|
93
|
+
"chai": "^4.3.4",
|
|
94
|
+
"chai-match": "^1.1.1",
|
|
95
|
+
"eslint": "^8.11.0",
|
|
96
|
+
"mocha": "^10.0.0",
|
|
97
|
+
"sinon": "^9.2.4"
|
|
98
|
+
},
|
|
99
|
+
"oclif": {
|
|
100
|
+
"bin": "apify",
|
|
101
|
+
"commands": "./src/commands",
|
|
102
|
+
"hooks": {
|
|
103
|
+
"init": [
|
|
104
|
+
"./src/hooks/init"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
106
107
|
}
|
|
107
|
-
}
|
|
108
108
|
}
|
package/src/commands/create.js
CHANGED
|
@@ -3,6 +3,7 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const actorTemplates = require('@apify/actor-templates');
|
|
5
5
|
const unzipper = require('unzipper');
|
|
6
|
+
const semver = require('semver');
|
|
6
7
|
const { ApifyCommand } = require('../lib/apify_command');
|
|
7
8
|
const execWithLog = require('../lib/exec');
|
|
8
9
|
const outputs = require('../lib/outputs');
|
|
@@ -15,8 +16,10 @@ const {
|
|
|
15
16
|
detectPythonVersion,
|
|
16
17
|
isPythonVersionSupported,
|
|
17
18
|
getPythonCommand,
|
|
19
|
+
detectNodeVersion,
|
|
20
|
+
isNodeVersionSupported,
|
|
18
21
|
} = require('../lib/utils');
|
|
19
|
-
const { EMPTY_LOCAL_CONFIG, LOCAL_CONFIG_PATH, PYTHON_VENV_PATH } = require('../lib/consts');
|
|
22
|
+
const { EMPTY_LOCAL_CONFIG, LOCAL_CONFIG_PATH, PYTHON_VENV_PATH, SUPPORTED_NODEJS_VERSION } = require('../lib/consts');
|
|
20
23
|
const { httpsGet, ensureValidActorName, getTemplateDefinition } = require('../lib/create-utils');
|
|
21
24
|
|
|
22
25
|
class CreateCommand extends ApifyCommand {
|
|
@@ -76,14 +79,25 @@ class CreateCommand extends ApifyCommand {
|
|
|
76
79
|
let dependenciesInstalled = false;
|
|
77
80
|
if (!skipDependencyInstall) {
|
|
78
81
|
if (fs.existsSync(packageJsonPath)) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
const currentNodeVersion = detectNodeVersion();
|
|
83
|
+
const minimumSupportedNodeVersion = semver.minVersion(SUPPORTED_NODEJS_VERSION);
|
|
84
|
+
if (currentNodeVersion) {
|
|
85
|
+
if (!isNodeVersionSupported(currentNodeVersion)) {
|
|
86
|
+
outputs.warning(`You are running Node.js version ${currentNodeVersion}, which is no longer supported. `
|
|
87
|
+
+ `Please upgrade to Node.js version ${minimumSupportedNodeVersion} or later.`);
|
|
88
|
+
}
|
|
89
|
+
// If the actor is a Node.js actor (has package.json), run `npm install`
|
|
90
|
+
await updateLocalJson(packageJsonPath, { name: actorName });
|
|
91
|
+
// Run npm install in actor dir.
|
|
92
|
+
// For efficiency, don't install Puppeteer for templates that don't use it
|
|
93
|
+
const cmdArgs = ['install'];
|
|
94
|
+
if (skipOptionalDeps) cmdArgs.push('--no-optional');
|
|
95
|
+
await execWithLog(getNpmCmd(), cmdArgs, { cwd: actFolderDir });
|
|
96
|
+
dependenciesInstalled = true;
|
|
97
|
+
} else {
|
|
98
|
+
outputs.error(`No Node.js detected! Please install Node.js ${minimumSupportedNodeVersion} or higher`
|
|
99
|
+
+ ' to be able to run Node.js actors locally.');
|
|
100
|
+
}
|
|
87
101
|
} else if (fs.existsSync(requirementsTxtPath)) {
|
|
88
102
|
const pythonVersion = detectPythonVersion(actFolderDir);
|
|
89
103
|
if (pythonVersion) {
|
package/src/commands/run.js
CHANGED
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
getLocalUserInfo, purgeDefaultQueue, purgeDefaultKeyValueStore,
|
|
12
12
|
purgeDefaultDataset, getLocalConfigOrThrow, getNpmCmd, checkIfStorageIsEmpty,
|
|
13
13
|
detectPythonVersion, isPythonVersionSupported, getPythonCommand,
|
|
14
|
+
detectNodeVersion, isNodeVersionSupported,
|
|
14
15
|
} = require('../lib/utils');
|
|
15
16
|
const { error, info, warning } = require('../lib/outputs');
|
|
16
17
|
const { replaceSecretsValue } = require('../lib/secrets');
|
|
@@ -86,26 +87,30 @@ class RunCommand extends ApifyCommand {
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
if (packageJsonExists) { // Actor is written in Node.js
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
const currentNodeVersion = detectNodeVersion();
|
|
91
|
+
const minimumSupportedNodeVersion = semver.minVersion(SUPPORTED_NODEJS_VERSION);
|
|
92
|
+
if (currentNodeVersion) {
|
|
93
|
+
const serverJsFile = path.join(cwd, 'server.js');
|
|
94
|
+
const packageJson = await loadJson(packageJsonPath);
|
|
95
|
+
if ((!packageJson.scripts || !packageJson.scripts.start) && !fs.existsSync(serverJsFile)) {
|
|
96
|
+
throw new Error('The "npm start" script was not found in package.json. Please set it up for your project. '
|
|
97
|
+
+ 'For more information about that call "apify help run".');
|
|
98
|
+
}
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
// --max-http-header-size=80000
|
|
101
|
+
// Increases default size of headers. The original limit was 80kb, but from node 10+ they decided to lower it to 8kb.
|
|
102
|
+
// However they did not think about all the sites there with large headers,
|
|
103
|
+
// so we put back the old limit of 80kb, which seems to work just fine.
|
|
104
|
+
if (isNodeVersionSupported(currentNodeVersion)) {
|
|
105
|
+
env.NODE_OPTIONS = env.NODE_OPTIONS ? `${env.NODE_OPTIONS} --max-http-header-size=80000` : '--max-http-header-size=80000';
|
|
106
|
+
} else {
|
|
107
|
+
warning(`You are running Node.js version ${currentNodeVersion}, which is no longer supported. `
|
|
108
|
+
+ `Please upgrade to Node.js version ${minimumSupportedNodeVersion} or later.`);
|
|
109
|
+
}
|
|
110
|
+
await execWithLog(getNpmCmd(), ['start'], { env });
|
|
104
111
|
} else {
|
|
105
|
-
|
|
106
|
-
+ `Please upgrade to Node.js version ${lastSupportedVersion} or later.`);
|
|
112
|
+
error(`No Node.js detected! Please install Node.js ${minimumSupportedNodeVersion} or higher to be able to run Node.js actors locally.`);
|
|
107
113
|
}
|
|
108
|
-
await execWithLog(getNpmCmd(), ['start'], { env });
|
|
109
114
|
} else if (mainPyExists) {
|
|
110
115
|
const pythonVersion = detectPythonVersion(cwd);
|
|
111
116
|
if (pythonVersion) {
|
package/src/lib/utils.js
CHANGED
|
@@ -20,6 +20,7 @@ const https = require('https');
|
|
|
20
20
|
const { ApifyClient } = require('apify-client');
|
|
21
21
|
const {
|
|
22
22
|
execSync,
|
|
23
|
+
spawnSync,
|
|
23
24
|
} = require('child_process');
|
|
24
25
|
const semver = require('semver');
|
|
25
26
|
const {
|
|
@@ -31,6 +32,7 @@ const {
|
|
|
31
32
|
DEPRECATED_LOCAL_CONFIG_NAME,
|
|
32
33
|
ACTOR_SPECIFICATION_VERSION,
|
|
33
34
|
APIFY_CLIENT_DEFAULT_HEADERS,
|
|
35
|
+
SUPPORTED_NODEJS_VERSION,
|
|
34
36
|
MINIMUM_SUPPORTED_PYTHON_VERSION,
|
|
35
37
|
} = require('./consts');
|
|
36
38
|
const {
|
|
@@ -518,7 +520,10 @@ const getPythonCommand = (directory) => {
|
|
|
518
520
|
const detectPythonVersion = (directory) => {
|
|
519
521
|
const pythonCommand = getPythonCommand(directory);
|
|
520
522
|
try {
|
|
521
|
-
|
|
523
|
+
const spawnResult = spawnSync(pythonCommand, ['-c', 'import platform; print(platform.python_version())'], { encoding: 'utf-8' });
|
|
524
|
+
if (!spawnResult.error && spawnResult.stdout) {
|
|
525
|
+
return spawnResult.stdout.trim();
|
|
526
|
+
}
|
|
522
527
|
} catch {
|
|
523
528
|
return undefined;
|
|
524
529
|
}
|
|
@@ -528,6 +533,24 @@ const isPythonVersionSupported = (installedPythonVersion) => {
|
|
|
528
533
|
return semver.satisfies(installedPythonVersion, `^${MINIMUM_SUPPORTED_PYTHON_VERSION}`);
|
|
529
534
|
};
|
|
530
535
|
|
|
536
|
+
const detectNodeVersion = () => {
|
|
537
|
+
try {
|
|
538
|
+
const spawnResult = spawnSync('node', ['--version'], { encoding: 'utf-8' });
|
|
539
|
+
if (!spawnResult.error && spawnResult.stdout) {
|
|
540
|
+
return spawnResult.stdout.trim().replace(/^v/, '');
|
|
541
|
+
}
|
|
542
|
+
} catch {
|
|
543
|
+
return undefined;
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const isNodeVersionSupported = (installedNodeVersion) => {
|
|
548
|
+
// SUPPORTED_NODEJS_VERSION can be a version range,
|
|
549
|
+
// we need to get the minimum supported version from that range to be able to compare them
|
|
550
|
+
const minimumSupportedNodeVersion = semver.minVersion(SUPPORTED_NODEJS_VERSION);
|
|
551
|
+
return semver.gte(installedNodeVersion, minimumSupportedNodeVersion);
|
|
552
|
+
};
|
|
553
|
+
|
|
531
554
|
module.exports = {
|
|
532
555
|
getLoggedClientOrThrow,
|
|
533
556
|
getLocalConfig,
|
|
@@ -558,4 +581,6 @@ module.exports = {
|
|
|
558
581
|
detectPythonVersion,
|
|
559
582
|
isPythonVersionSupported,
|
|
560
583
|
getPythonCommand,
|
|
584
|
+
detectNodeVersion,
|
|
585
|
+
isNodeVersionSupported,
|
|
561
586
|
};
|
package/src/lib/version_check.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const fs = require('fs');
|
|
2
2
|
const process = require('process');
|
|
3
3
|
const axios = require('axios');
|
|
4
4
|
const chalk = require('chalk');
|
|
@@ -37,7 +37,7 @@ const detectInstallationType = () => {
|
|
|
37
37
|
// If the real command path is like `/opt/homebrew/Cellar/apify-cli/...` or `/home/linuxbrew/.linuxbrew/Cellar/apify-cli/...`,
|
|
38
38
|
// then the CLI is installed via Homebrew
|
|
39
39
|
if (process.platform === 'linux' || process.platform === 'darwin') {
|
|
40
|
-
const realCommandPath =
|
|
40
|
+
const realCommandPath = fs.realpathSync(commandPath);
|
|
41
41
|
if (realCommandPath.includes('homebrew/Cellar') || realCommandPath.includes('linuxbrew/Cellar')) {
|
|
42
42
|
return INSTALLATION_TYPE.HOMEBREW;
|
|
43
43
|
}
|