apify-cli 0.18.2-beta.0 → 0.18.2-beta.10

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.
Files changed (41) hide show
  1. package/README.md +4 -0
  2. package/oclif.manifest.json +1 -1
  3. package/package.json +25 -22
  4. package/src/commands/actor/get-input.js +1 -1
  5. package/src/commands/actor/get-value.js +1 -1
  6. package/src/commands/actor/index.js +1 -0
  7. package/src/commands/actor/push-data.js +1 -1
  8. package/src/commands/actor/set-value.js +2 -1
  9. package/src/commands/call.js +4 -3
  10. package/src/commands/check-version.js +1 -0
  11. package/src/commands/create.js +13 -19
  12. package/src/commands/edit-input-schema.js +3 -4
  13. package/src/commands/info.js +1 -0
  14. package/src/commands/init-wrap-scrapy.js +34 -0
  15. package/src/commands/init.js +30 -5
  16. package/src/commands/login-new.js +3 -4
  17. package/src/commands/login.js +2 -1
  18. package/src/commands/logout.js +1 -1
  19. package/src/commands/pull.js +6 -4
  20. package/src/commands/push.js +8 -6
  21. package/src/commands/run.js +24 -10
  22. package/src/commands/secrets/index.js +1 -0
  23. package/src/commands/vis.js +1 -0
  24. package/src/lib/actor.js +5 -3
  25. package/src/lib/apify_command.js +6 -4
  26. package/src/lib/consts.js +6 -0
  27. package/src/lib/create-utils.js +6 -25
  28. package/src/lib/exec.js +1 -0
  29. package/src/lib/files.js +3 -2
  30. package/src/lib/input_schema.js +5 -3
  31. package/src/lib/local_state.js +1 -0
  32. package/src/lib/project_analyzer.js +24 -0
  33. package/src/lib/scrapy-wrapper/ScrapyProjectAnalyzer.js +90 -0
  34. package/src/lib/scrapy-wrapper/Spider.js +10 -0
  35. package/src/lib/scrapy-wrapper/SpiderFileAnalyzer.js +26 -0
  36. package/src/lib/scrapy-wrapper/index.js +139 -0
  37. package/src/lib/secrets.js +2 -2
  38. package/src/lib/telemetry.js +4 -2
  39. package/src/lib/utils.js +55 -18
  40. package/src/lib/version_check.js +6 -13
  41. package/npm-shrinkwrap.json +0 -14224
package/README.md CHANGED
@@ -449,6 +449,10 @@ USAGE
449
449
  ARGUMENTS
450
450
  ACTORNAME Name of the actor. If not provided, you will be prompted for it.
451
451
 
452
+ OPTIONS
453
+ -y, --yes Automatic yes to prompts; assume "yes" as answer to all prompts. Note that in some cases, the command may
454
+ still ask for confirmation.
455
+
452
456
  DESCRIPTION
453
457
  The command only creates the ".actor/actor.json" file and the "storage" directory in the current directory, but will
454
458
  not touch anything else.
@@ -1 +1 @@
1
- {"version":"0.18.2","commands":{"call":{"id":"call","description":"Runs a specific actor remotely on the Apify cloud platform.\nThe Actor is run under your current Apify account. Therefore you need to be logged in by calling \"apify login\". It takes input for the Actor from the default local key-value store by default.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"build":{"name":"build","type":"option","char":"b","description":"Tag or number of the build to run (e.g. \"latest\" or \"1.2.34\").","required":false},"timeout":{"name":"timeout","type":"option","char":"t","description":"Timeout for the actor run in seconds. Zero value means there is no timeout.","required":false},"memory":{"name":"memory","type":"option","char":"m","description":"Amount of memory allocated for the actor run, in megabytes.","required":false},"wait-for-finish":{"name":"wait-for-finish","type":"option","char":"w","description":"Seconds for waiting to run to finish, if no value passed, it waits forever.","required":false}},"args":[{"name":"actId","description":"Name or ID of the actor to run (e.g. \"apify/hello-world\" or \"E2jjCZBezvAZnX8Rb\"). If not provided, the command runs the remote actor specified in the \".actor/actor.json\" file.","required":false}]},"check-version":{"id":"check-version","description":"Checks that installed Apify CLI version is up to date.","pluginName":"apify-cli","pluginType":"core","hidden":true,"aliases":["cv"],"flags":{"enforce-update":{"name":"enforce-update","type":"boolean","char":"e","description":"[Optional] Enforce version update from NPM","required":false,"allowNo":false}},"args":[]},"create":{"id":"create","description":"Creates a new actor project directory from a selected boilerplate template.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"template":{"name":"template","type":"option","char":"t","description":"Template for the actor. If not provided, the command will prompt for it.\nVisit https://raw.githubusercontent.com/apify/actor-templates/master/templates/manifest.json to find available template names.","required":false},"skip-dependency-install":{"name":"skip-dependency-install","type":"boolean","description":"Skip installing actor dependencies.","required":false,"allowNo":false},"template-archive-url":{"name":"template-archive-url","type":"option","description":"Actor template archive url. Useful for developing new templates.","hidden":true,"required":false}},"args":[{"name":"actorName","description":"Name of the actor and its directory","required":false}]},"edit-input-schema":{"id":"edit-input-schema","description":"Lets you edit your input schema that would be used on the platform in a visual input schema editor.","pluginName":"apify-cli","pluginType":"core","hidden":true,"aliases":["eis"],"flags":{},"args":[{"name":"path","description":"Optional path to your INPUT_SCHEMA.json file. If not provided default platform location for input schema is used.","required":false}]},"info":{"id":"info","description":"Displays information about the currently active Apify account.\nThe information is printed to the console.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"init":{"id":"init","description":"Initializes a new actor project in an existing directory.\nThe command only creates the \".actor/actor.json\" file and the \"storage\" directory in the current directory, but will not touch anything else.\n\nWARNING: The directory at \"storage\" will be overwritten if it already exists.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"actorName","description":"Name of the actor. If not provided, you will be prompted for it.","required":false}]},"login-new":{"id":"login-new","description":"Logs in to your Apify account using your API token.\nThe API token and other account information is stored in the ~/.apify directory, from where it is read by all other \"apify\" commands. To log out, call \"apify logout\".","pluginName":"apify-cli","pluginType":"core","hidden":true,"aliases":[],"flags":{"token":{"name":"token","type":"option","char":"t","description":"[Optional] Apify API token","required":false}},"args":[]},"login":{"id":"login","description":"Logs in to your Apify account using a provided API token.\nThe API token and other account information is stored in the ~/.apify directory, from where it is read by all other \"apify\" commands. To log out, call \"apify logout\".","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"token":{"name":"token","type":"option","char":"t","description":"[Optional] Apify API token","required":false}},"args":[]},"logout":{"id":"logout","description":"Logs out of your Apify account.\nThe command deletes the API token and all other account information stored in the ~/.apify directory. To log in again, call \"apify login\".","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"pull":{"id":"pull","description":"Pulls an Actor from the Apify platform to the current directory. If it is defined as Git repository, it will be cloned. If it is defined as Web IDE, it will fetch the files.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"version":{"name":"version","type":"option","char":"v","description":"Actor version number which will be pulled, e.g. 1.2. Default: the highest version","required":false}},"args":[{"name":"actorId","description":"Name or ID of the actor to run (e.g. \"apify/hello-world\" or \"E2jjCZBezvAZnX8Rb\"). If not provided, the command will update the Actor in the current directory based on its name in \".actor/actor.json\" file.","required":false}]},"push":{"id":"push","description":"Uploads the actor to the Apify platform and builds it there.\nThe Actor settings are read from the \".actor/actor.json\" file in the current directory, but they can be overridden using command-line options.\nNOTE: If the source files are smaller than 3 MB then they are uploaded as \n\"Multiple source files\", otherwise they are uploaded as \"Zip file\".\n\nWARNING: If the target Actor already exists in your Apify account, it will be overwritten!","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"version-number":{"name":"version-number","type":"option","description":"DEPRECATED: Use flag version instead. Actor version number to which the files should be pushed. By default, it is taken from the \".actor/actor.json\" file.","required":false},"version":{"name":"version","type":"option","char":"v","description":"Actor version number to which the files should be pushed. By default, it is taken from the \".actor/actor.json\" file.","required":false},"build-tag":{"name":"build-tag","type":"option","char":"b","description":"Build tag to be applied to the successful Actor build. By default, it is taken from the \".actor/actor.json\" file","required":false},"wait-for-finish":{"name":"wait-for-finish","type":"option","char":"w","description":"Seconds for waiting to build to finish, if no value passed, it waits forever.","required":false},"no-prompt":{"name":"no-prompt","type":"boolean","description":"Do not prompt for opening the actor details in a browser. This will also not open the browser automatically.","required":false,"allowNo":false}},"args":[{"name":"actorId","description":"Name or ID of the Actor to push (e.g. \"apify/hello-world\" or \"E2jjCZBezvAZnX8Rb\"). If not provided, the command will create or modify the actor with the name specified in \".actor/actor.json\" file.","required":false}]},"run":{"id":"run","description":"Runs the actor locally in the current directory.\nIt sets various APIFY_XYZ environment variables in order to provide a working execution environment for the actor. For example, this causes the actor input, as well as all other data in key-value stores, datasets or request queues to be stored in the \"storage\" directory, rather than on the Apify platform.\n\nNOTE: You can override the command's default behavior for Node.js actors by overriding the \"start\" script in the package.json file. You can set up your own main file or environment variables by changing it.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"purge":{"name":"purge","type":"boolean","char":"p","description":"Shortcut that combines the --purge-queue, --purge-dataset and --purge-key-value-store options.","required":false,"allowNo":false},"purge-queue":{"name":"purge-queue","type":"boolean","description":"Deletes the local directory containing the default request queue before the run starts.","required":false,"allowNo":false},"purge-dataset":{"name":"purge-dataset","type":"boolean","description":"Deletes the local directory containing the default dataset before the run starts.","required":false,"allowNo":false},"purge-key-value-store":{"name":"purge-key-value-store","type":"boolean","description":"Deletes all records from the default key-value store in the local directory before the run starts, except for the \"INPUT\" key.","required":false,"allowNo":false}},"args":[]},"vis":{"id":"vis","description":"Validates input schema and prints errors found.\nThe input schema for the actor is used from these locations in order of preference.\nThe first one found is validated as it would be the one used on the Apify platform.\n1. Directly embedded object in \".actor/actor.json\" under 'input' key\n2. Path to JSON file referenced in \".actor/actor.json\" under 'input' key\n3. JSON file at .actor/INPUT_SCHEMA.json\n4. JSON file at INPUT_SCHEMA.json\n\nYou can also pass any custom path to your input schema to have it validated instead.\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"path","description":"Optional path to your INPUT_SCHEMA.json file. If not provided ./INPUT_SCHEMA.json is used.","required":false}]},"actor:get-input":{"id":"actor:get-input","description":"Gets the actor input value from the default key-value store associated with the actor run.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"actor:get-value":{"id":"actor:get-value","description":"Gets a value from the default key-value store associated with the actor run.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"key","description":"Key of the record in key-value store","required":true}]},"actor":{"id":"actor","description":"Commands are designed to be used in actor runs. All commands are in PoC state, do not use in production environments.\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"actor:push-data":{"id":"actor:push-data","description":"Stores an object or an array of objects to the default dataset of the actor run.\nIt is possible to pass data using item argument or stdin.\nPassing data using argument:\n$ apify actor:push-data {\"foo\": \"bar\"}\nPassing data using stdin with pipe:\n$ cat ./test.json | apify actor:push-data\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"item","description":"JSON string with one object or array of objects containing data to be stored in the default dataset.","required":false}]},"actor:set-value":{"id":"actor:set-value","description":"Sets or removes record into the default KeyValueStore associated with the actor run.\nIt is possible to pass data using argument or stdin.\nPassing data using argument:\n$ apify actor:set-value KEY my-value\nPassing data using stdin with pipe:\n$ cat ./my-text-file.txt | apify actor:set-value KEY --contentType text/plain\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"contentType":{"name":"contentType","type":"option","char":"c","description":"Specifies a custom MIME content type of the record. By default \"application/json\" is used.","required":false}},"args":[{"name":"key","description":"Key of the record in key-value store.","required":true},{"name":"value","description":"Record data, which can be one of the following values:\n- If empty, the record in the key-value store is deleted.\n- If no `contentType` flag is specified, value is expected to be any JSON string value.\n- If options.contentType is set, value is taken as is.","required":false}]},"secrets:add":{"id":"secrets:add","description":"Adds a new secret value.\nThe secrets are stored to a file at ~/.apify","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"name","description":"Name of the secret","required":true},{"name":"value","description":"Value of the secret","required":true}]},"secrets":{"id":"secrets","description":"Manages secret values for actor environment variables.\n\nExample:\n$ apify secrets:add mySecret TopSecretValue123\n\nNow the \"mySecret\" value can be used in an environment variable defined in \".actor/actor.json\" file by adding the \"@\" prefix:\n\n{\n \"actorSpecification\": 1,\n \"name\": \"my_actor\",\n \"environmentVariables\": { \"SECRET_ENV_VAR\": \"@mySecret\" },\n \"version\": \"0.1\n}\n\nWhen the actor is pushed to Apify cloud, the \"SECRET_ENV_VAR\" and its value is stored as a secret environment variable of the actor.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"secrets:rm":{"id":"secrets:rm","description":"Removes the secret.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"name","description":"Name of the secret","required":true}]}}}
1
+ {"version":"0.18.2","commands":{"call":{"id":"call","description":"Runs a specific actor remotely on the Apify cloud platform.\nThe Actor is run under your current Apify account. Therefore you need to be logged in by calling \"apify login\". It takes input for the Actor from the default local key-value store by default.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"build":{"name":"build","type":"option","char":"b","description":"Tag or number of the build to run (e.g. \"latest\" or \"1.2.34\").","required":false},"timeout":{"name":"timeout","type":"option","char":"t","description":"Timeout for the actor run in seconds. Zero value means there is no timeout.","required":false},"memory":{"name":"memory","type":"option","char":"m","description":"Amount of memory allocated for the actor run, in megabytes.","required":false},"wait-for-finish":{"name":"wait-for-finish","type":"option","char":"w","description":"Seconds for waiting to run to finish, if no value passed, it waits forever.","required":false}},"args":[{"name":"actId","description":"Name or ID of the actor to run (e.g. \"apify/hello-world\" or \"E2jjCZBezvAZnX8Rb\"). If not provided, the command runs the remote actor specified in the \".actor/actor.json\" file.","required":false}]},"check-version":{"id":"check-version","description":"Checks that installed Apify CLI version is up to date.","pluginName":"apify-cli","pluginType":"core","hidden":true,"aliases":["cv"],"flags":{"enforce-update":{"name":"enforce-update","type":"boolean","char":"e","description":"[Optional] Enforce version update from NPM","required":false,"allowNo":false}},"args":[]},"create":{"id":"create","description":"Creates a new actor project directory from a selected boilerplate template.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"template":{"name":"template","type":"option","char":"t","description":"Template for the actor. If not provided, the command will prompt for it.\nVisit https://raw.githubusercontent.com/apify/actor-templates/master/templates/manifest.json to find available template names.","required":false},"skip-dependency-install":{"name":"skip-dependency-install","type":"boolean","description":"Skip installing actor dependencies.","required":false,"allowNo":false},"template-archive-url":{"name":"template-archive-url","type":"option","description":"Actor template archive url. Useful for developing new templates.","hidden":true,"required":false}},"args":[{"name":"actorName","description":"Name of the actor and its directory","required":false}]},"edit-input-schema":{"id":"edit-input-schema","description":"Lets you edit your input schema that would be used on the platform in a visual input schema editor.","pluginName":"apify-cli","pluginType":"core","hidden":true,"aliases":["eis"],"flags":{},"args":[{"name":"path","description":"Optional path to your INPUT_SCHEMA.json file. If not provided default platform location for input schema is used.","required":false}]},"info":{"id":"info","description":"Displays information about the currently active Apify account.\nThe information is printed to the console.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"init-wrap-scrapy":{"id":"init-wrap-scrapy","description":"Wraps your existing Scrapy project to work like an Apify Actor.\n\nIt adds the following features:\n- Automatic retry of failed requests\n- Automatic proxy rotation\n- Automatic user agent rotation\n...\n","pluginName":"apify-cli","pluginType":"core","hidden":true,"aliases":[],"flags":{},"args":[{"name":"path","description":"Optional path to your scrapy project. If not provided, the current directory is used.","required":false}]},"init":{"id":"init","description":"Initializes a new actor project in an existing directory.\nThe command only creates the \".actor/actor.json\" file and the \"storage\" directory in the current directory, but will not touch anything else.\n\nWARNING: The directory at \"storage\" will be overwritten if it already exists.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Automatic yes to prompts; assume \"yes\" as answer to all prompts. Note that in some cases, the command may still ask for confirmation.","required":false,"allowNo":false}},"args":[{"name":"actorName","description":"Name of the actor. If not provided, you will be prompted for it.","required":false}]},"login-new":{"id":"login-new","description":"Logs in to your Apify account using your API token.\nThe API token and other account information is stored in the ~/.apify directory, from where it is read by all other \"apify\" commands. To log out, call \"apify logout\".","pluginName":"apify-cli","pluginType":"core","hidden":true,"aliases":[],"flags":{"token":{"name":"token","type":"option","char":"t","description":"[Optional] Apify API token","required":false}},"args":[]},"login":{"id":"login","description":"Logs in to your Apify account using a provided API token.\nThe API token and other account information is stored in the ~/.apify directory, from where it is read by all other \"apify\" commands. To log out, call \"apify logout\".","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"token":{"name":"token","type":"option","char":"t","description":"[Optional] Apify API token","required":false}},"args":[]},"logout":{"id":"logout","description":"Logs out of your Apify account.\nThe command deletes the API token and all other account information stored in the ~/.apify directory. To log in again, call \"apify login\".","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"pull":{"id":"pull","description":"Pulls an Actor from the Apify platform to the current directory. If it is defined as Git repository, it will be cloned. If it is defined as Web IDE, it will fetch the files.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"version":{"name":"version","type":"option","char":"v","description":"Actor version number which will be pulled, e.g. 1.2. Default: the highest version","required":false}},"args":[{"name":"actorId","description":"Name or ID of the actor to run (e.g. \"apify/hello-world\" or \"E2jjCZBezvAZnX8Rb\"). If not provided, the command will update the Actor in the current directory based on its name in \".actor/actor.json\" file.","required":false}]},"push":{"id":"push","description":"Uploads the actor to the Apify platform and builds it there.\nThe Actor settings are read from the \".actor/actor.json\" file in the current directory, but they can be overridden using command-line options.\nNOTE: If the source files are smaller than 3 MB then they are uploaded as \n\"Multiple source files\", otherwise they are uploaded as \"Zip file\".\n\nWARNING: If the target Actor already exists in your Apify account, it will be overwritten!","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"version-number":{"name":"version-number","type":"option","description":"DEPRECATED: Use flag version instead. Actor version number to which the files should be pushed. By default, it is taken from the \".actor/actor.json\" file.","required":false},"version":{"name":"version","type":"option","char":"v","description":"Actor version number to which the files should be pushed. By default, it is taken from the \".actor/actor.json\" file.","required":false},"build-tag":{"name":"build-tag","type":"option","char":"b","description":"Build tag to be applied to the successful Actor build. By default, it is taken from the \".actor/actor.json\" file","required":false},"wait-for-finish":{"name":"wait-for-finish","type":"option","char":"w","description":"Seconds for waiting to build to finish, if no value passed, it waits forever.","required":false},"no-prompt":{"name":"no-prompt","type":"boolean","description":"Do not prompt for opening the actor details in a browser. This will also not open the browser automatically.","required":false,"allowNo":false}},"args":[{"name":"actorId","description":"Name or ID of the Actor to push (e.g. \"apify/hello-world\" or \"E2jjCZBezvAZnX8Rb\"). If not provided, the command will create or modify the actor with the name specified in \".actor/actor.json\" file.","required":false}]},"run":{"id":"run","description":"Runs the actor locally in the current directory.\nIt sets various APIFY_XYZ environment variables in order to provide a working execution environment for the actor. For example, this causes the actor input, as well as all other data in key-value stores, datasets or request queues to be stored in the \"storage\" directory, rather than on the Apify platform.\n\nNOTE: You can override the command's default behavior for Node.js actors by overriding the \"start\" script in the package.json file. You can set up your own main file or environment variables by changing it.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"purge":{"name":"purge","type":"boolean","char":"p","description":"Shortcut that combines the --purge-queue, --purge-dataset and --purge-key-value-store options.","required":false,"allowNo":false},"purge-queue":{"name":"purge-queue","type":"boolean","description":"Deletes the local directory containing the default request queue before the run starts.","required":false,"allowNo":false},"purge-dataset":{"name":"purge-dataset","type":"boolean","description":"Deletes the local directory containing the default dataset before the run starts.","required":false,"allowNo":false},"purge-key-value-store":{"name":"purge-key-value-store","type":"boolean","description":"Deletes all records from the default key-value store in the local directory before the run starts, except for the \"INPUT\" key.","required":false,"allowNo":false}},"args":[]},"vis":{"id":"vis","description":"Validates input schema and prints errors found.\nThe input schema for the actor is used from these locations in order of preference.\nThe first one found is validated as it would be the one used on the Apify platform.\n1. Directly embedded object in \".actor/actor.json\" under 'input' key\n2. Path to JSON file referenced in \".actor/actor.json\" under 'input' key\n3. JSON file at .actor/INPUT_SCHEMA.json\n4. JSON file at INPUT_SCHEMA.json\n\nYou can also pass any custom path to your input schema to have it validated instead.\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"path","description":"Optional path to your INPUT_SCHEMA.json file. If not provided ./INPUT_SCHEMA.json is used.","required":false}]},"actor:get-input":{"id":"actor:get-input","description":"Gets the actor input value from the default key-value store associated with the actor run.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"actor:get-value":{"id":"actor:get-value","description":"Gets a value from the default key-value store associated with the actor run.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"key","description":"Key of the record in key-value store","required":true}]},"actor":{"id":"actor","description":"Commands are designed to be used in actor runs. All commands are in PoC state, do not use in production environments.\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"actor:push-data":{"id":"actor:push-data","description":"Stores an object or an array of objects to the default dataset of the actor run.\nIt is possible to pass data using item argument or stdin.\nPassing data using argument:\n$ apify actor:push-data {\"foo\": \"bar\"}\nPassing data using stdin with pipe:\n$ cat ./test.json | apify actor:push-data\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"item","description":"JSON string with one object or array of objects containing data to be stored in the default dataset.","required":false}]},"actor:set-value":{"id":"actor:set-value","description":"Sets or removes record into the default KeyValueStore associated with the actor run.\nIt is possible to pass data using argument or stdin.\nPassing data using argument:\n$ apify actor:set-value KEY my-value\nPassing data using stdin with pipe:\n$ cat ./my-text-file.txt | apify actor:set-value KEY --contentType text/plain\n","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{"contentType":{"name":"contentType","type":"option","char":"c","description":"Specifies a custom MIME content type of the record. By default \"application/json\" is used.","required":false}},"args":[{"name":"key","description":"Key of the record in key-value store.","required":true},{"name":"value","description":"Record data, which can be one of the following values:\n- If empty, the record in the key-value store is deleted.\n- If no `contentType` flag is specified, value is expected to be any JSON string value.\n- If options.contentType is set, value is taken as is.","required":false}]},"secrets:add":{"id":"secrets:add","description":"Adds a new secret value.\nThe secrets are stored to a file at ~/.apify","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"name","description":"Name of the secret","required":true},{"name":"value","description":"Value of the secret","required":true}]},"secrets":{"id":"secrets","description":"Manages secret values for actor environment variables.\n\nExample:\n$ apify secrets:add mySecret TopSecretValue123\n\nNow the \"mySecret\" value can be used in an environment variable defined in \".actor/actor.json\" file by adding the \"@\" prefix:\n\n{\n \"actorSpecification\": 1,\n \"name\": \"my_actor\",\n \"environmentVariables\": { \"SECRET_ENV_VAR\": \"@mySecret\" },\n \"version\": \"0.1\n}\n\nWhen the actor is pushed to Apify cloud, the \"SECRET_ENV_VAR\" and its value is stored as a secret environment variable of the actor.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[]},"secrets:rm":{"id":"secrets:rm","description":"Removes the secret.","pluginName":"apify-cli","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"name","description":"Name of the secret","required":true}]}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apify-cli",
3
- "version": "0.18.2-beta.0",
3
+ "version": "0.18.2-beta.10",
4
4
  "description": "Apify command-line interface helps you create, develop, build and run Apify actors, and manage the Apify cloud platform.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -53,54 +53,57 @@
53
53
  "node": ">=16.0.0"
54
54
  },
55
55
  "dependencies": {
56
- "@apify/actor-templates": "^0.1.3",
57
- "@apify/consts": "^2.20.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",
56
+ "@apify/actor-templates": "^0.1.4",
57
+ "@apify/consts": "^2.23.0",
58
+ "@apify/input_schema": "^3.5.8",
59
+ "@apify/utilities": "^2.9.3",
60
+ "@crawlee/memory-storage": "^3.5.8",
61
+ "@oclif/command": "^1.8.36",
62
+ "@oclif/config": "^1.18.17",
63
+ "@oclif/errors": "^1.3.6",
64
64
  "@oclif/plugin-commands": "^2.1.0",
65
65
  "@oclif/plugin-help": "^5.1.12",
66
+ "@root/walk": "^1.1.0",
66
67
  "adm-zip": "^0.5.10",
67
- "ajv": "^8.10.0",
68
- "apify-client": "^2.2.0",
68
+ "ajv": "^8.12.0",
69
+ "apify-client": "^2.8.2",
69
70
  "archiver-promise": "^1.0.0",
70
- "axios": "^0.21.1",
71
+ "axios": "^1.6.1",
71
72
  "chalk": "^4.1.2",
72
73
  "computer-name": "^0.1.0",
74
+ "configparser": "^0.3.10",
73
75
  "cors": "^2.8.5",
74
76
  "detect-indent": "^6.1.0",
75
77
  "escape-string-regexp": "^4.0.0",
76
78
  "express": "^4.18.2",
77
79
  "globby": "^11.1.0",
80
+ "handlebars": "^4.7.8",
78
81
  "inquirer": "^7.3.3",
79
82
  "is-ci": "^3.0.1",
80
83
  "is-online": "^10.0.0",
81
- "istextorbinary": "^6.0.0",
84
+ "istextorbinary": "^8.0.0",
82
85
  "jju": "^1.4.0",
83
86
  "load-json-file": "^6.2.0",
84
- "mime": "^2.6.0",
85
- "mixpanel": "^0.17.0",
87
+ "mime": "^3.0.0",
88
+ "mixpanel": "^0.18.0",
86
89
  "open": "^8.4.0",
87
- "ow": "^0.28.1",
90
+ "ow": "^0.28.2",
88
91
  "rimraf": "^3.0.2",
89
- "semver": "^7.3.5",
90
- "tiged": "^2.12.4",
91
- "underscore": "^1.13.2",
92
+ "semver": "^7.5.4",
93
+ "tiged": "^2.12.5",
94
+ "underscore": "^1.13.6",
92
95
  "write-json-file": "^4.3.0"
93
96
  },
94
97
  "devDependencies": {
95
- "@apify/eslint-config": "^0.2.3",
98
+ "@apify/eslint-config": "^0.4.0",
96
99
  "@oclif/dev-cli": "^1.26.0",
97
100
  "@oclif/test": "^2.1.0",
98
101
  "chai": "^4.3.4",
99
102
  "chai-match": "^1.1.1",
100
103
  "cross-env": "^7.0.3",
101
- "eslint": "^8.11.0",
104
+ "eslint": "^8.53.0",
102
105
  "mocha": "^10.0.0",
103
- "sinon": "^9.2.4"
106
+ "sinon": "^17.0.0"
104
107
  },
105
108
  "oclif": {
106
109
  "bin": "apify",
@@ -1,5 +1,5 @@
1
- const { ApifyCommand } = require('../../lib/apify_command');
2
1
  const { outputInputFromDefaultStore } = require('../../lib/actor');
2
+ const { ApifyCommand } = require('../../lib/apify_command');
3
3
 
4
4
  class GetInputCommand extends ApifyCommand {
5
5
  async run() {
@@ -1,5 +1,5 @@
1
- const { ApifyCommand } = require('../../lib/apify_command');
2
1
  const { outputRecordFromDefaultStore } = require('../../lib/actor');
2
+ const { ApifyCommand } = require('../../lib/apify_command');
3
3
 
4
4
  class GetValueCommand extends ApifyCommand {
5
5
  async run() {
@@ -1,4 +1,5 @@
1
1
  const { Command } = require('@oclif/command');
2
+
2
3
  const { showHelpForCommand } = require('../../lib/utils');
3
4
 
4
5
  class ActorIndexCommand extends Command {
@@ -1,5 +1,5 @@
1
- const { ApifyCommand } = require('../../lib/apify_command');
2
1
  const { getApifyStorageClient, getDefaultStorageId, APIFY_STORAGE_TYPES } = require('../../lib/actor');
2
+ const { ApifyCommand } = require('../../lib/apify_command');
3
3
 
4
4
  class PushDataCommand extends ApifyCommand {
5
5
  async init() {
@@ -1,6 +1,7 @@
1
1
  const { flags: flagsHelper } = require('@oclif/command');
2
- const { ApifyCommand } = require('../../lib/apify_command');
2
+
3
3
  const { getApifyStorageClient, getDefaultStorageId, APIFY_STORAGE_TYPES } = require('../../lib/actor');
4
+ const { ApifyCommand } = require('../../lib/apify_command');
4
5
 
5
6
  class SetValueCommand extends ApifyCommand {
6
7
  async init() {
@@ -1,11 +1,12 @@
1
- const { flags: flagsHelper } = require('@oclif/command');
2
1
  const { ACT_JOB_STATUSES } = require('@apify/consts');
2
+ const { flags: flagsHelper } = require('@oclif/command');
3
3
  const mime = require('mime');
4
+
4
5
  const { ApifyCommand } = require('../lib/apify_command');
6
+ const { LOCAL_CONFIG_PATH } = require('../lib/consts');
7
+ const outputs = require('../lib/outputs');
5
8
  const { getLocalConfig, getLoggedClientOrThrow,
6
9
  getLocalUserInfo, getLocalInput, outputJobLog } = require('../lib/utils');
7
- const outputs = require('../lib/outputs');
8
- const { LOCAL_CONFIG_PATH } = require('../lib/consts');
9
10
 
10
11
  // TODO: Show full error messages and HTTP codes, this is not great:
11
12
  // jan:testx$ apify call help
@@ -1,4 +1,5 @@
1
1
  const { flags: flagsHelper } = require('@oclif/command');
2
+
2
3
  const { ApifyCommand } = require('../lib/apify_command');
3
4
  const { checkLatestVersion } = require('../lib/version_check');
4
5
 
@@ -1,15 +1,21 @@
1
- const { flags: flagsHelper } = require('@oclif/command');
2
1
  const fs = require('fs');
3
2
  const path = require('path');
4
- const { finished } = require('stream');
5
- const { promisify } = require('util');
3
+
6
4
  const actorTemplates = require('@apify/actor-templates');
7
- const AdmZip = require('adm-zip');
5
+ const { flags: flagsHelper } = require('@oclif/command');
8
6
  const semver = require('semver');
7
+
9
8
  const { ApifyCommand } = require('../lib/apify_command');
9
+ const { EMPTY_LOCAL_CONFIG, LOCAL_CONFIG_PATH, PYTHON_VENV_PATH, SUPPORTED_NODEJS_VERSION } = require('../lib/consts');
10
+ const {
11
+ ensureValidActorName,
12
+ getTemplateDefinition,
13
+ enhanceReadmeWithLocalSuffix,
14
+ } = require('../lib/create-utils');
10
15
  const execWithLog = require('../lib/exec');
11
- const outputs = require('../lib/outputs');
12
16
  const { updateLocalJson } = require('../lib/files');
17
+ const { createPrefilledInputFileFromInputSchema } = require('../lib/input_schema');
18
+ const outputs = require('../lib/outputs');
13
19
  const {
14
20
  setLocalConfig,
15
21
  setLocalEnv,
@@ -21,15 +27,8 @@ const {
21
27
  detectNodeVersion,
22
28
  isNodeVersionSupported,
23
29
  detectNpmVersion,
30
+ downloadAndUnzip,
24
31
  } = require('../lib/utils');
25
- const { EMPTY_LOCAL_CONFIG, LOCAL_CONFIG_PATH, PYTHON_VENV_PATH, SUPPORTED_NODEJS_VERSION } = require('../lib/consts');
26
- const {
27
- httpsGet,
28
- ensureValidActorName,
29
- getTemplateDefinition,
30
- enhanceReadmeWithLocalSuffix,
31
- } = require('../lib/create-utils');
32
- const { createPrefilledInputFileFromInputSchema } = require('../lib/input_schema');
33
32
 
34
33
  class CreateCommand extends ApifyCommand {
35
34
  async run() {
@@ -79,12 +78,7 @@ class CreateCommand extends ApifyCommand {
79
78
  throw err;
80
79
  }
81
80
 
82
- const zipStream = await httpsGet(templateArchiveUrl);
83
- const chunks = [];
84
- zipStream.on('data', (chunk) => chunks.push(chunk));
85
- await promisify(finished)(zipStream);
86
- const zip = new AdmZip(Buffer.concat(chunks));
87
- zip.extractAllTo(actFolderDir, true);
81
+ await downloadAndUnzip({ url: templateArchiveUrl, pathTo: actFolderDir });
88
82
 
89
83
  // There may be .actor/actor.json file in used template - let's try to load it and change the name prop value to actorName
90
84
  const localConfig = await getJsonFileContent(path.join(actFolderDir, LOCAL_CONFIG_PATH));
@@ -1,17 +1,16 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
+ const { cryptoRandomObjectId } = require('@apify/utilities');
4
5
  const cors = require('cors');
5
6
  const detectIndent = require('detect-indent');
6
7
  const express = require('express');
7
8
  const open = require('open');
8
9
 
9
- const { cryptoRandomObjectId } = require('@apify/utilities');
10
-
11
10
  const { ApifyCommand } = require('../lib/apify_command');
12
- const outputs = require('../lib/outputs');
13
- const { readInputSchema } = require('../lib/input_schema');
14
11
  const { LOCAL_CONFIG_PATH } = require('../lib/consts');
12
+ const { readInputSchema } = require('../lib/input_schema');
13
+ const outputs = require('../lib/outputs');
15
14
 
16
15
  const INPUT_SCHEMA_EDITOR_BASE_URL = 'https://apify.github.io/input-schema-editor-react/';
17
16
  const INPUT_SCHEMA_EDITOR_ORIGIN = new URL(INPUT_SCHEMA_EDITOR_BASE_URL).origin;
@@ -1,4 +1,5 @@
1
1
  const chalk = require('chalk');
2
+
2
3
  const { ApifyCommand } = require('../lib/apify_command');
3
4
  const { getLoggedClientOrThrow, getLocalUserInfo } = require('../lib/utils');
4
5
 
@@ -0,0 +1,34 @@
1
+ const { ApifyCommand } = require('../lib/apify_command');
2
+ const { info } = require('../lib/outputs');
3
+ const { wrapScrapyProject } = require('../lib/scrapy-wrapper/index');
4
+
5
+ class WrapScrapyCommand extends ApifyCommand {
6
+ async run() {
7
+ const { args } = this.parse(WrapScrapyCommand);
8
+
9
+ await wrapScrapyProject({ projectPath: args.path });
10
+
11
+ info('Scrapy project wrapped successfully.');
12
+ }
13
+ }
14
+
15
+ WrapScrapyCommand.hidden = true;
16
+
17
+ WrapScrapyCommand.description = `Wraps your existing Scrapy project to work like an Apify Actor.
18
+
19
+ It adds the following features:
20
+ - Automatic retry of failed requests
21
+ - Automatic proxy rotation
22
+ - Automatic user agent rotation
23
+ ...
24
+ `;
25
+
26
+ WrapScrapyCommand.args = [
27
+ {
28
+ name: 'path',
29
+ required: false,
30
+ description: 'Optional path to your scrapy project. If not provided, the current directory is used.',
31
+ },
32
+ ];
33
+
34
+ module.exports = WrapScrapyCommand;
@@ -1,17 +1,34 @@
1
- const inquirer = require('inquirer');
2
1
  const path = require('path');
2
+
3
+ const { flags: flagsHelper } = require('@oclif/command');
4
+ const inquirer = require('inquirer');
5
+
3
6
  const { ApifyCommand } = require('../lib/apify_command');
4
- const outputs = require('../lib/outputs');
5
- const { setLocalConfig, setLocalEnv, getLocalConfig, getLocalConfigOrThrow } = require('../lib/utils');
6
- const { EMPTY_LOCAL_CONFIG, DEFAULT_LOCAL_STORAGE_DIR, LOCAL_CONFIG_PATH } = require('../lib/consts');
7
+ const { EMPTY_LOCAL_CONFIG, DEFAULT_LOCAL_STORAGE_DIR, LOCAL_CONFIG_PATH, LANGUAGE, PROJECT_TYPES } = require('../lib/consts');
7
8
  const { createPrefilledInputFileFromInputSchema } = require('../lib/input_schema');
9
+ const outputs = require('../lib/outputs');
10
+ const { ProjectAnalyzer } = require('../lib/project_analyzer');
11
+ const { wrapScrapyProject } = require('../lib/scrapy-wrapper');
12
+ const { setLocalConfig, setLocalEnv, getLocalConfig, getLocalConfigOrThrow, detectLocalActorLanguage } = require('../lib/utils');
8
13
 
9
14
  class InitCommand extends ApifyCommand {
10
15
  async run() {
11
- const { args } = this.parse(InitCommand);
16
+ const { args, flags } = this.parse(InitCommand);
12
17
  let { actorName } = args;
13
18
  const cwd = process.cwd();
14
19
 
20
+ if (ProjectAnalyzer.getProjectType(cwd) === PROJECT_TYPES.SCRAPY) {
21
+ outputs.info('The current directory looks like a Scrapy project. Using automatic project wrapping.');
22
+
23
+ return wrapScrapyProject({ projectPath: cwd });
24
+ }
25
+
26
+ if (!flags.yes && detectLocalActorLanguage(cwd).language === LANGUAGE.UNKNOWN) {
27
+ outputs.warning('The current directory does not look like a Node.js or Python project.');
28
+ const { c } = await inquirer.prompt([{ name: 'c', message: 'Do you want to continue?', type: 'confirm' }]);
29
+ if (!c) return;
30
+ }
31
+
15
32
  if (getLocalConfig()) {
16
33
  outputs.warning(`Skipping creation of "${LOCAL_CONFIG_PATH}", the file already exists in the current directory.`);
17
34
  } else {
@@ -43,4 +60,12 @@ InitCommand.args = [
43
60
  },
44
61
  ];
45
62
 
63
+ InitCommand.flags = {
64
+ yes: flagsHelper.boolean({
65
+ char: 'y',
66
+ description: 'Automatic yes to prompts; assume "yes" as answer to all prompts. Note that in some cases, the command may still ask for confirmation.',
67
+ required: false,
68
+ }),
69
+ };
70
+
46
71
  module.exports = InitCommand;
@@ -1,17 +1,16 @@
1
+ const { cryptoRandomObjectId } = require('@apify/utilities');
1
2
  const { flags: flagsHelper } = require('@oclif/command');
2
3
  const computerName = require('computer-name');
3
4
  const cors = require('cors');
4
5
  const express = require('express');
6
+ const inquirer = require('inquirer');
5
7
  const open = require('open');
6
8
 
7
- const { cryptoRandomObjectId } = require('@apify/utilities');
8
-
9
- const inquirer = require('inquirer');
10
9
  const { ApifyCommand } = require('../lib/apify_command');
11
10
  const outputs = require('../lib/outputs');
11
+ const { useApifyIdentity } = require('../lib/telemetry');
12
12
  const { getLoggedClient } = require('../lib/utils');
13
13
  const { getLocalUserInfo } = require('../lib/utils');
14
- const { useApifyIdentity } = require('../lib/telemetry');
15
14
 
16
15
  const CONSOLE_BASE_URL = 'https://console.apify.com/account?tab=integrations';
17
16
  // const CONSOLE_BASE_URL = 'http://localhost:3000/account?tab=integrations';
@@ -1,10 +1,11 @@
1
1
  const { flags: flagsHelper } = require('@oclif/command');
2
2
  const inquirer = require('inquirer');
3
+
3
4
  const { ApifyCommand } = require('../lib/apify_command');
4
5
  const { success, error } = require('../lib/outputs');
6
+ const { useApifyIdentity } = require('../lib/telemetry');
5
7
  const { getLoggedClient } = require('../lib/utils');
6
8
  const { getLocalUserInfo } = require('../lib/utils');
7
- const { useApifyIdentity } = require('../lib/telemetry');
8
9
 
9
10
  class LoginCommand extends ApifyCommand {
10
11
  async run() {
@@ -1,7 +1,7 @@
1
1
  const { ApifyCommand } = require('../lib/apify_command');
2
2
  const { AUTH_FILE_PATH } = require('../lib/consts');
3
- const { success } = require('../lib/outputs');
4
3
  const { rimrafPromised } = require('../lib/files');
4
+ const { success } = require('../lib/outputs');
5
5
  const { regenerateLocalDistinctId } = require('../lib/telemetry');
6
6
 
7
7
  class LogoutCommand extends ApifyCommand {
@@ -1,15 +1,17 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const tiged = require('tiged');
3
+
4
+ const { flags: flagsHelper } = require('@oclif/command');
4
5
  const AdmZip = require('adm-zip');
5
- const semverGt = require('semver/functions/gt');
6
6
  const { get } = require('axios');
7
- const { flags: flagsHelper } = require('@oclif/command');
8
7
  const jju = require('jju');
8
+ const semverGt = require('semver/functions/gt');
9
+ const tiged = require('tiged');
10
+
9
11
  const { ApifyCommand } = require('../lib/apify_command');
12
+ const { LOCAL_CONFIG_PATH } = require('../lib/consts');
10
13
  const { success, error } = require('../lib/outputs');
11
14
  const { getLoggedClientOrThrow, getLocalConfigOrThrow, getLocalUserInfo } = require('../lib/utils');
12
- const { LOCAL_CONFIG_PATH } = require('../lib/consts');
13
15
 
14
16
  const extractGitHubZip = async (url, directoryPath) => {
15
17
  const { data } = await get(url, { responseType: 'arraybuffer' });
@@ -1,19 +1,21 @@
1
1
  const fs = require('fs');
2
- const { flags: flagsHelper } = require('@oclif/command');
2
+
3
3
  const actorTemplates = require('@apify/actor-templates');
4
4
  const { ACT_JOB_STATUSES, ACT_SOURCE_TYPES,
5
5
  MAX_MULTIFILE_BYTES } = require('@apify/consts');
6
- const open = require('open');
6
+ const { flags: flagsHelper } = require('@oclif/command');
7
7
  const inquirer = require('inquirer');
8
8
  const isCI = require('is-ci');
9
+ const open = require('open');
10
+
9
11
  const { ApifyCommand } = require('../lib/apify_command');
12
+ const { UPLOADS_STORE_NAME, LOCAL_CONFIG_PATH } = require('../lib/consts');
13
+ const { sumFilesSizeInBytes } = require('../lib/files');
14
+ const outputs = require('../lib/outputs');
15
+ const { transformEnvToEnvVars } = require('../lib/secrets');
10
16
  const { createActZip, getLoggedClientOrThrow,
11
17
  outputJobLog, getLocalUserInfo, getActorLocalFilePaths,
12
18
  createSourceFiles, getLocalConfigOrThrow } = require('../lib/utils');
13
- const { sumFilesSizeInBytes } = require('../lib/files');
14
- const { UPLOADS_STORE_NAME, LOCAL_CONFIG_PATH } = require('../lib/consts');
15
- const { transformEnvToEnvVars } = require('../lib/secrets');
16
- const outputs = require('../lib/outputs');
17
19
 
18
20
  const TEMP_ZIP_FILE_NAME = 'temp_file.zip';
19
21
  const DEFAULT_RUN_OPTIONS = {
@@ -1,19 +1,23 @@
1
- const { flags: flagsHelper } = require('@oclif/command');
2
1
  const fs = require('fs');
3
2
  const path = require('path');
4
- const loadJson = require('load-json-file');
3
+
5
4
  const { APIFY_ENV_VARS } = require('@apify/consts');
5
+ const { flags: flagsHelper } = require('@oclif/command');
6
+ const loadJson = require('load-json-file');
6
7
  const semver = require('semver');
7
- const execWithLog = require('../lib/exec');
8
- const { LEGACY_LOCAL_STORAGE_DIR, DEFAULT_LOCAL_STORAGE_DIR, SUPPORTED_NODEJS_VERSION, LANGUAGE } = require('../lib/consts');
8
+
9
9
  const { ApifyCommand } = require('../lib/apify_command');
10
+ const { LEGACY_LOCAL_STORAGE_DIR, DEFAULT_LOCAL_STORAGE_DIR, SUPPORTED_NODEJS_VERSION, LANGUAGE, PROJECT_TYPES } = require('../lib/consts');
11
+ const execWithLog = require('../lib/exec');
12
+ const { error, info, warning } = require('../lib/outputs');
13
+ const { ProjectAnalyzer } = require('../lib/project_analyzer');
14
+ const { ScrapyProjectAnalyzer } = require('../lib/scrapy-wrapper/ScrapyProjectAnalyzer');
15
+ const { replaceSecretsValue } = require('../lib/secrets');
10
16
  const {
11
17
  getLocalUserInfo, purgeDefaultQueue, purgeDefaultKeyValueStore,
12
18
  purgeDefaultDataset, getLocalConfigOrThrow, getNpmCmd, checkIfStorageIsEmpty,
13
19
  detectLocalActorLanguage, isPythonVersionSupported, getPythonCommand, isNodeVersionSupported,
14
20
  } = require('../lib/utils');
15
- const { error, info, warning } = require('../lib/outputs');
16
- const { replaceSecretsValue } = require('../lib/secrets');
17
21
 
18
22
  class RunCommand extends ApifyCommand {
19
23
  async run() {
@@ -27,11 +31,12 @@ class RunCommand extends ApifyCommand {
27
31
 
28
32
  const packageJsonExists = fs.existsSync(packageJsonPath);
29
33
  const mainPyExists = fs.existsSync(mainPyPath);
34
+ const isScrapyProject = ProjectAnalyzer.getProjectType(cwd) === PROJECT_TYPES.SCRAPY;
30
35
 
31
- if (!packageJsonExists && !mainPyExists) {
36
+ if (!packageJsonExists && !mainPyExists && !isScrapyProject) {
32
37
  throw new Error(
33
- 'Actor is of an uknown format.'
34
- + ` Make sure either the 'package.json' file or 'src/__main__.py' file exists.`,
38
+ 'Actor is of an unknown format.'
39
+ + ` Make sure either the 'package.json' file or 'src/__main__.py' file exists or you are in a migrated Scrapy project.`,
35
40
  );
36
41
  }
37
42
 
@@ -120,7 +125,16 @@ class RunCommand extends ApifyCommand {
120
125
  if (pythonVersion) {
121
126
  if (isPythonVersionSupported(pythonVersion)) {
122
127
  const pythonCommand = getPythonCommand(cwd);
123
- await execWithLog(pythonCommand, ['-m', 'src'], { env });
128
+ if (isScrapyProject) {
129
+ const project = new ScrapyProjectAnalyzer(cwd);
130
+ project.loadScrapyCfg();
131
+ if (!project.configuration.hasKey('apify', 'mainpy_location')) {
132
+ throw new Error(`This Scrapy project's configuration does not contain Apify settings. Did you forget to run "apify init"?`);
133
+ }
134
+ await execWithLog(pythonCommand, ['-m', project.configuration.get('apify', 'mainpy_location')], { env });
135
+ } else {
136
+ await execWithLog(pythonCommand, ['-m', 'src'], { env });
137
+ }
124
138
  } else {
125
139
  error(`Python actors require Python 3.8 or higher, but you have Python ${pythonVersion}!`);
126
140
  error('Please install Python 3.8 or higher to be able to run Python actors locally.');
@@ -1,4 +1,5 @@
1
1
  const { Command } = require('@oclif/command');
2
+
2
3
  const { LOCAL_CONFIG_PATH } = require('../../lib/consts');
3
4
  const { showHelpForCommand } = require('../../lib/utils');
4
5
 
@@ -1,5 +1,6 @@
1
1
  const { validateInputSchema } = require('@apify/input_schema');
2
2
  const Ajv = require('ajv');
3
+
3
4
  const { ApifyCommand } = require('../lib/apify_command');
4
5
  const { LOCAL_CONFIG_PATH } = require('../lib/consts');
5
6
  const { readInputSchema } = require('../lib/input_schema');
package/src/lib/actor.js CHANGED
@@ -1,9 +1,11 @@
1
- const { ApifyClient } = require('apify-client');
2
1
  const { pipeline } = require('stream');
3
2
  const { promisify } = require('util');
4
- const { default: ow } = require('ow');
5
- const { MemoryStorage } = require('@crawlee/memory-storage');
3
+
6
4
  const { ACTOR_ENV_VARS, LOCAL_ACTOR_ENV_VARS, APIFY_ENV_VARS, KEY_VALUE_STORE_KEYS } = require('@apify/consts');
5
+ const { MemoryStorage } = require('@crawlee/memory-storage');
6
+ const { ApifyClient } = require('apify-client');
7
+ const { default: ow } = require('ow');
8
+
7
9
  const { getLocalUserInfo, getLocalStorageDir, getApifyClientOptions } = require('./utils');
8
10
 
9
11
  const pipelinePromise = promisify(pipeline);