From 0d10f4268bdd89f7515486ae2ec281ccf85c3a4d Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Fri, 17 Oct 2025 16:27:48 +0200 Subject: [PATCH 1/2] chore: Update texts in apify create flow --- src/commands/create.ts | 25 +++++++++++++------------ src/lib/create-utils.ts | 27 +++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/commands/create.ts b/src/commands/create.ts index f9f41cf1d..f1bb3888f 100644 --- a/src/commands/create.ts +++ b/src/commands/create.ts @@ -16,7 +16,12 @@ import { PYTHON_VENV_PATH, SUPPORTED_NODEJS_VERSION, } from '../lib/consts.js'; -import { enhanceReadmeWithLocalSuffix, ensureValidActorName, getTemplateDefinition } from '../lib/create-utils.js'; +import { + enhanceReadmeWithLocalSuffix, + ensureValidActorName, + formatCreateSuccessMessage, + getTemplateDefinition, +} from '../lib/create-utils.js'; import { execWithLog } from '../lib/exec.js'; import { updateLocalJson } from '../lib/files.js'; import { usePythonRuntime } from '../lib/hooks/runtimes/python.js'; @@ -329,17 +334,13 @@ export class CreateCommand extends ApifyCommand { } } - if (dependenciesInstalled) { - success({ message: `Actor '${actorName}' was created. To run it, run "cd ${actorName}" and "apify run".` }); - info({ message: 'To run your code in the cloud, run "apify push" and deploy your code to Apify Console.' }); - if (messages?.postCreate) { - info({ message: messages?.postCreate }); - } - } else { - success({ - message: `Actor '${actorName}' was created. Please install its dependencies to be able to run it using "apify run".`, - }); - } + success({ + message: formatCreateSuccessMessage({ + actorName, + dependenciesInstalled, + postCreate: messages?.postCreate ?? null, + }), + }); // Report git initialization result after actor creation success if (!skipGitInit && !cwdHasGit) { diff --git a/src/lib/create-utils.ts b/src/lib/create-utils.ts index b5b455603..b6101fb63 100644 --- a/src/lib/create-utils.ts +++ b/src/lib/create-utils.ts @@ -66,6 +66,30 @@ export async function enhanceReadmeWithLocalSuffix(readmePath: string, manifestP } } +export function formatCreateSuccessMessage(params: { + actorName: string; + dependenciesInstalled: boolean; + postCreate?: string | null; +}) { + const { actorName, dependenciesInstalled, postCreate } = params; + + let message = `āœ… Actor '${actorName}' created successfully!`; + + if (dependenciesInstalled) { + message += `\n\nNext steps:\n\ncd '${actorName}'\napify run`; + } else { + message += `\n\nNext steps:\n\ncd '${actorName}'\ninstall dependencies\napify run`; + } + + message += `\n\nšŸ’” Tip: Use 'apify push' to deploy your Actor to the Apify platform\nšŸ“– Docs: https://docs.apify.com/platform/actors/development`; + + if (postCreate) { + message += `\n\n${postCreate}`; + } + + return message; +} + /** * Inquirer does not have a native way to "go back" between prompts. */ @@ -134,8 +158,7 @@ async function promptTemplateDefinition(manifest: Manifest, programmingLanguage: ]; const templateDefinition = await useSelectFromList({ - message: - 'Choose a template for your new Actor. Detailed information about the template will be shown in the next step.', + message: 'Choose a template for your new Actor. You can check more information at https://apify.com/templates.', default: choices[0], choices, loop: false, From 5a4e6b9a493875721b475144e6bc223a2961368f Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Wed, 22 Oct 2025 13:36:45 +0200 Subject: [PATCH 2/2] feat: improve texts in create flow --- src/commands/create.ts | 69 ++++++++++++++++++++++++++++++----------- src/lib/create-utils.ts | 25 ++++++++------- src/lib/outputs.ts | 7 +++-- 3 files changed, 69 insertions(+), 32 deletions(-) diff --git a/src/commands/create.ts b/src/commands/create.ts index f1bb3888f..f9ba617ce 100644 --- a/src/commands/create.ts +++ b/src/commands/create.ts @@ -334,25 +334,58 @@ export class CreateCommand extends ApifyCommand { } } - success({ - message: formatCreateSuccessMessage({ - actorName, - dependenciesInstalled, - postCreate: messages?.postCreate ?? null, - }), - }); + // Suggest install command if dependencies were not installed + let installCommandSuggestion: string | null = null; + if (!dependenciesInstalled) { + const projectInfo = await useCwdProject({ cwd: actFolderDir }); + await projectInfo.inspectAsync(async (project) => { + if (project.type === ProjectLanguage.JavaScript) { + const hasYarnLock = await stat(join(actFolderDir, 'yarn.lock')) + .then(() => true) + .catch(() => false); + const hasPnpmLock = await stat(join(actFolderDir, 'pnpm-lock.yaml')) + .then(() => true) + .catch(() => false); + const hasBunLock = await stat(join(actFolderDir, 'bun.lockb')) + .then(() => true) + .catch(() => false); + if (hasYarnLock) { + installCommandSuggestion = 'yarn install'; + } else if (hasPnpmLock) { + installCommandSuggestion = 'pnpm install'; + } else if (hasBunLock) { + installCommandSuggestion = 'bun install'; + } else if (project.runtime?.pmName === 'bun') { + installCommandSuggestion = 'bun install'; + } else if (project.runtime?.pmName === 'deno') { + installCommandSuggestion = 'deno install --node-modules-dir'; + } else { + installCommandSuggestion = 'npm install'; + } + } else if (project.type === ProjectLanguage.Python || project.type === ProjectLanguage.Scrapy) { + installCommandSuggestion = 'python -m pip install -r requirements.txt'; + } + }); + } - // Report git initialization result after actor creation success - if (!skipGitInit && !cwdHasGit) { - if (gitInitResult.success) { - info({ - message: `Git repository initialized in '${actorName}'. You can now commit and push your Actor to Git.`, - }); - } else { - // Git init is not critical, so we just warn if it fails - warning({ message: `Failed to initialize git repository: ${gitInitResult.error!.message}` }); - warning({ message: 'You can manually run "git init" in the Actor directory if needed.' }); - } + success( + { + message: formatCreateSuccessMessage({ + actorName, + dependenciesInstalled, + postCreate: messages?.postCreate ?? null, + gitRepositoryInitialized: !skipGitInit && !cwdHasGit && gitInitResult.success, + installCommandSuggestion, + }), + }, + true, + ); + + // Report git initialization result only if it failed (success already included in success message) + if (!skipGitInit && !cwdHasGit && !gitInitResult.success) { + // Git init is not critical, so we just warn if it fails + warning({ message: `Failed to initialize git repository: ${gitInitResult.error!.message}` }); + warning({ message: 'You can manually run "git init" in the Actor directory if needed.' }); } } } diff --git a/src/lib/create-utils.ts b/src/lib/create-utils.ts index b6101fb63..a5a9fe538 100644 --- a/src/lib/create-utils.ts +++ b/src/lib/create-utils.ts @@ -2,7 +2,6 @@ import { createWriteStream } from 'node:fs'; import { pipeline } from 'node:stream/promises'; import { Separator } from '@inquirer/core'; -import chalk from 'chalk'; import type { Manifest, Template } from '@apify/actor-templates'; @@ -70,19 +69,26 @@ export function formatCreateSuccessMessage(params: { actorName: string; dependenciesInstalled: boolean; postCreate?: string | null; + gitRepositoryInitialized?: boolean; + installCommandSuggestion?: string | null; }) { - const { actorName, dependenciesInstalled, postCreate } = params; + const { actorName, dependenciesInstalled, postCreate, gitRepositoryInitialized, installCommandSuggestion } = params; let message = `āœ… Actor '${actorName}' created successfully!`; if (dependenciesInstalled) { message += `\n\nNext steps:\n\ncd '${actorName}'\napify run`; } else { - message += `\n\nNext steps:\n\ncd '${actorName}'\ninstall dependencies\napify run`; + const installLine = installCommandSuggestion || 'install dependencies'; + message += `\n\nNext steps:\n\ncd '${actorName}'\n${installLine}\napify run`; } message += `\n\nšŸ’” Tip: Use 'apify push' to deploy your Actor to the Apify platform\nšŸ“– Docs: https://docs.apify.com/platform/actors/development`; + if (gitRepositoryInitialized) { + message += `\n🌱 Git repository initialized in '${actorName}'. You can now commit and push your Actor to Git.`; + } + if (postCreate) { message += `\n\n${postCreate}`; } @@ -99,7 +105,7 @@ async function executePrompts(manifest: Manifest) { while (true) { const templateDefinition = await promptTemplateDefinition(manifest, programmingLanguage); if (templateDefinition) { - const shouldInstall = await promptTemplateInstallation(templateDefinition); + const shouldInstall = await promptTemplateInstallation(); if (shouldInstall) { return templateDefinition; } @@ -168,20 +174,15 @@ async function promptTemplateDefinition(manifest: Manifest, programmingLanguage: return templateDefinition; } -async function promptTemplateInstallation(templateDefinition: Template) { +async function promptTemplateInstallation() { const choices: ChoicesType = [ - { name: `Install template`, value: true }, + { name: `Install dependencies`, value: true }, new Separator(), { name: 'Go back', value: false }, ]; - const label = chalk.underline(templateDefinition.label); - const description = chalk.dim(templateDefinition.description); - const suffix = `\n ${label}:\n ${description}`; - const message = `Do you want to install the following template?${suffix}`; - const answer = await useSelectFromList({ - message, + message: 'Almost done! Last step is to install dependencies.', default: choices[0], choices, loop: false, diff --git a/src/lib/outputs.ts b/src/lib/outputs.ts index 33e58cbbb..e364fe346 100644 --- a/src/lib/outputs.ts +++ b/src/lib/outputs.ts @@ -38,9 +38,12 @@ export function warning(options: SimpleLogOptions) { }); } -export function success(options: SimpleLogOptions) { +export function success(options: SimpleLogOptions, newLine = false) { internalLog({ - [options.stdout ? 'stdoutOutput' : 'stderrOutput']: [chalk.green('Success:'), options.message], + [options.stdout ? 'stdoutOutput' : 'stderrOutput']: [ + chalk.green(`${newLine ? '\n' : ''}Success:`), + options.message, + ], }); }