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 CHANGED
@@ -1,108 +1,108 @@
1
1
  {
2
- "name": "apify-cli",
3
- "version": "0.15.0-beta.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
- ]
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
  }
@@ -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
- // If the actor is a Node.js actor (has package.json), run `npm install`
80
- await updateLocalJson(packageJsonPath, { name: actorName });
81
- // Run npm install in actor dir.
82
- // For efficiency, don't install Puppeteer for templates that don't use it
83
- const cmdArgs = ['install'];
84
- if (skipOptionalDeps) cmdArgs.push('--no-optional');
85
- await execWithLog(getNpmCmd(), cmdArgs, { cwd: actFolderDir });
86
- dependenciesInstalled = true;
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) {
@@ -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 serverJsFile = path.join(cwd, 'server.js');
90
- const packageJson = await loadJson(packageJsonPath);
91
- if ((!packageJson.scripts || !packageJson.scripts.start) && !fs.existsSync(serverJsFile)) {
92
- throw new Error('The "npm start" script was not found in package.json. Please set it up for your project. '
93
- + 'For more information about that call "apify help run".');
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
- // --max-http-header-size=80000
97
- // Increases default size of headers. The original limit was 80kb, but from node 10+ they decided to lower it to 8kb.
98
- // However they did not think about all the sites there with large headers,
99
- // so we put back the old limit of 80kb, which seems to work just fine.
100
- const currentNodeVersion = process.versions.node;
101
- const lastSupportedVersion = semver.minVersion(SUPPORTED_NODEJS_VERSION);
102
- if (semver.gte(currentNodeVersion, lastSupportedVersion)) {
103
- env.NODE_OPTIONS = env.NODE_OPTIONS ? `${env.NODE_OPTIONS} --max-http-header-size=80000` : '--max-http-header-size=80000';
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
- warning(`You are running Node.js version ${currentNodeVersion}, which is no longer supported. `
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
- return execSync(`${pythonCommand} -c "import platform; print(platform.python_version(), end='')"`, { encoding: 'utf-8' });
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
  };
@@ -1,4 +1,4 @@
1
- const { execSync } = require('child_process');
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 = execSync(`realpath "${commandPath}"`);
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
  }