Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,19 @@ DESCRIPTION
directory.

USAGE
$ apify create [actorName] [--omit-optional-deps]
$ apify create [actorName]
[-l javascript|typescript|python|other] [--omit-optional-deps]
[--skip-dependency-install] [--skip-git-init] [-t <value>]
[-u web-scraping|ai-agent|api-pipeline|browser-automation]

ARGUMENTS
actorName Name of the Actor and its directory.

FLAGS
-l, --language=<option> Filter templates by
programming language. Ignored when --template is
provided.
<options: javascript|typescript|python|other>
--omit-optional-deps Skip installing optional
dependencies.
--skip-dependency-install Skip installing Actor
Expand All @@ -295,6 +301,37 @@ FLAGS
it. Visit
https://raw.githubusercontent.com/apify/actor-templates/master/templates/manifest.json
to find available template names.
-u, --use-case=<option> Filter templates by
what you want to build. Ignored when --template is
provided. Run "apify templates ls" to see the use
cases each template supports.
<options:
web-scraping|ai-agent|api-pipeline|browser-automation>
```

##### `apify templates`

```sh
DESCRIPTION
Explore the Actor templates used by "apify create".

SUBCOMMANDS
templates ls Prints all available Actor templates, including the
use cases and language each one supports.
```

##### `apify templates ls`

```sh
DESCRIPTION
Prints all available Actor templates, including the use cases and language
each one supports.

USAGE
$ apify templates ls [--json]

FLAGS
--json Format the command output as JSON.
```

##### `apify init`
Expand Down
2 changes: 2 additions & 0 deletions scripts/generate-cli-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const categories: Record<string, CommandsInCategory[]> = {
'actor-dev': [
//
{ command: Commands.create },
{ command: Commands.templates },
{ command: Commands.templatesLs },
{ command: Commands.init },
{ command: Commands.run },
{ command: Commands.validateSchema },
Expand Down
2 changes: 2 additions & 0 deletions src/commands/_register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { RunsIndexCommand } from './runs/_index.js';
import { SecretsIndexCommand } from './secrets/_index.js';
import { TasksIndexCommand } from './task/_index.js';
import { TelemetryIndexCommand } from './telemetry/_index.js';
import { TemplatesIndexCommand } from './templates/_index.js';
import { ValidateSchemaCommand } from './validate-schema.js';

export const apifyCommands = [
Expand All @@ -50,6 +51,7 @@ export const apifyCommands = [
SecretsIndexCommand,
TasksIndexCommand,
TelemetryIndexCommand,
TemplatesIndexCommand,

// top-level
ApiCommand,
Expand Down
18 changes: 16 additions & 2 deletions src/commands/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { getInstallCommandSuggestion } from '../lib/hooks/runtimes/utils.js';
import { ProjectLanguage, useCwdProject } from '../lib/hooks/useCwdProject.js';
import { createPrefilledInputFileFromInputSchema } from '../lib/input_schema.js';
import { error, info, simpleLog, success, warning } from '../lib/outputs.js';
import { LANGUAGE_FLAG_CHOICES, USE_CASE_FLAG_CHOICES } from '../lib/templates/consts.js';
import {
downloadAndUnzip,
getJsonFileContent,
Expand Down Expand Up @@ -74,6 +75,19 @@ export class CreateCommand extends ApifyCommand<typeof CreateCommand> {
description: `Template for the Actor. If not provided, the command will prompt for it. Visit ${manifestUrl} to find available template names.`,
required: false,
}),
'use-case': Flags.string({
char: 'u',
description:
'Filter templates by what you want to build. Ignored when --template is provided. Run "apify templates ls" to see the use cases each template supports.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Filter templates by what you want to build. Ignored when --template is provided. Run "apify templates ls" to see the use cases each template supports.',
'Filter templates by category. Ignored when --template is provided. To see the use cases each template supports, run "apify templates ls".',

choices: USE_CASE_FLAG_CHOICES,
required: false,
}),
language: Flags.string({
char: 'l',
description: 'Filter templates by programming language. Ignored when --template is provided.',
choices: LANGUAGE_FLAG_CHOICES,
required: false,
}),
'skip-dependency-install': Flags.boolean({
description: 'Skip installing Actor dependencies.',
required: false,
Expand Down Expand Up @@ -103,7 +117,7 @@ export class CreateCommand extends ApifyCommand<typeof CreateCommand> {

async run() {
let { actorName } = this.args;
const { template: templateName, skipDependencyInstall, skipGitInit } = this.flags;
const { template: templateName, useCase, language, skipDependencyInstall, skipGitInit } = this.flags;

// --template-archive-url is an internal, undocumented flag that's used
// for testing of templates that are not yet published in the manifest
Expand Down Expand Up @@ -156,7 +170,7 @@ export class CreateCommand extends ApifyCommand<typeof CreateCommand> {
};

if (!templateArchiveUrl) {
const templateDefinition = await getTemplateDefinition(templateName, manifestPromise);
const templateDefinition = await getTemplateDefinition(templateName, manifestPromise, { useCase, language });
({ archiveUrl: templateArchiveUrl, messages } = templateDefinition);
this.telemetryData.create.templateId = templateDefinition.id;
this.telemetryData.create.templateName = templateDefinition.name;
Expand Down
16 changes: 16 additions & 0 deletions src/commands/templates/_index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { TemplatesLsCommand } from './ls.js';

export class TemplatesIndexCommand extends ApifyCommand<typeof TemplatesIndexCommand> {
static override name = 'templates' as const;

static override description = 'Explore the Actor templates used by "apify create".';

static override group = 'Local Actor Development';

static override subcommands = [TemplatesLsCommand];

async run() {
this.printHelp();
}
}
63 changes: 63 additions & 0 deletions src/commands/templates/ls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { fetchManifest } from '@apify/actor-templates';

import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { CompactMode, ResponsiveTable } from '../../lib/commands/responsive-table.js';
import { info, simpleLog } from '../../lib/outputs.js';
import { printJsonToStdout } from '../../lib/utils.js';

const table = new ResponsiveTable({
allColumns: ['Template', 'Label', 'Language', 'Use cases'],
mandatoryColumns: ['Template', 'Language', 'Use cases'],
});

export class TemplatesLsCommand extends ApifyCommand<typeof TemplatesLsCommand> {
static override name = 'ls' as const;

static override description =
'Prints all available Actor templates, including the use cases and language each one supports.';

static override examples = [
{
description: 'List all available templates.',
command: 'apify templates ls',
},
{
description: 'List templates as JSON (includes the use-case tags for scripting).',
command: 'apify templates ls --json',
},
];

static override enableJsonFlag = true;

async run() {
const { json } = this.flags;

const manifest = await fetchManifest().catch((err) => {
throw new Error(`Could not fetch template list from server. Cause: ${(err as Error)?.message}`);
});

if (json) {
printJsonToStdout(manifest.templates);
return;
}

if (manifest.templates.length === 0) {
info({ message: 'There are no templates available.', stdout: true });
return;
}

for (const template of manifest.templates) {
table.pushRow({
Template: template.name,
Label: template.label,
Language: template.category,
'Use cases': (template.useCases ?? []).join(', '),
});
}

simpleLog({
message: table.render(CompactMode.WebLikeCompact),
stdout: true,
});
}
}
Loading