Skip to content
Draft
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
11 changes: 7 additions & 4 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ SUBCOMMANDS
to '~/.apify/auth.json'.
auth logout Removes authentication by deleting your API token and
account information from '~/.apify/auth.json'.
auth token Prints the current API token for the Apify CLI.
auth token Prints the API token the CLI would use, resolved from
APIFY_TOKEN or the stored login.
```

##### `apify auth login` / `apify login`
Expand All @@ -168,7 +169,8 @@ USAGE
FLAGS
-m, --method=<option> Method of logging in to Apify.
<options: console|manual>
-t, --token=<value> Apify API token.
-t, --token=<value> Apify API token to log in with and
save. APIFY_TOKEN is deliberately ignored here.
```

##### `apify auth logout` / `apify logout`
Expand All @@ -187,7 +189,8 @@ USAGE

```sh
DESCRIPTION
Prints the current API token for the Apify CLI.
Prints the API token the CLI would use, resolved from APIFY_TOKEN or the
stored login.

USAGE
$ apify auth token
Expand Down Expand Up @@ -1796,7 +1799,7 @@ ARGUMENTS

FLAGS
-t, --token=<value> Apify API token to embed in the config.
Defaults to the token from 'apify login'.
Defaults to APIFY_TOKEN, then the token from 'apify login'.
--tools=<value> Comma-separated tool IDs or Actor full names
to expose. Forwarded as a '?tools=' query parameter.
--url=<value> Apify MCP server URL.
Expand Down
9 changes: 2 additions & 7 deletions src/commands/actor/charge.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { APIFY_ENV_VARS } from '@apify/consts';

import { getApifyTokenFromEnvOrAuthFile } from '../../lib/actor.js';
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { Args } from '../../lib/command-framework/args.js';
import { Flags } from '../../lib/command-framework/flags.js';
import { info } from '../../lib/outputs.js';
import { getLoggedClient } from '../../lib/utils.js';
import { getLoggedClientOrThrow } from '../../lib/utils.js';

/**
* This command can be used to charge for a specific event in the pay-per-event Actor run.
Expand Down Expand Up @@ -86,11 +85,7 @@ export class ActorChargeCommand extends ApifyCommand<typeof ActorChargeCommand>
return;
}

const apifyToken = await getApifyTokenFromEnvOrAuthFile();
const apifyClient = await getLoggedClient(apifyToken);
if (!apifyClient) {
throw new Error('Apify token is not set. Please set it using the environment variable APIFY_TOKEN.');
}
const apifyClient = await getLoggedClientOrThrow();
const runId = process.env[APIFY_ENV_VARS.ACTOR_RUN_ID];

if (!runId) {
Expand Down
4 changes: 2 additions & 2 deletions src/commands/actors/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { runActorOrTaskOnCloud, SharedRunOnCloudFlags } from '../../lib/commands
import { finalizeRun, runUrl } from '../../lib/commands/run-result.js';
import { CommandExitCodes, LOCAL_CONFIG_PATH } from '../../lib/consts.js';
import { error, simpleLog } from '../../lib/outputs.js';
import { getLocalConfig, getLocalUserInfo, getLoggedClientOrThrow, TimestampFormatter } from '../../lib/utils.js';
import { getLocalConfig, getCurrentUserInfo, getLoggedClientOrThrow, TimestampFormatter } from '../../lib/utils.js';

export class ActorsCallCommand extends ApifyCommand<typeof ActorsCallCommand> {
static override name = 'call' as const;
Expand Down Expand Up @@ -102,7 +102,7 @@ export class ActorsCallCommand extends ApifyCommand<typeof ActorsCallCommand> {
const cwd = process.cwd();
const localConfig = getLocalConfig(cwd) || {};
const apifyClient = await getLoggedClientOrThrow();
const userInfo = await getLocalUserInfo();
const userInfo = await getCurrentUserInfo();
const usernameOrId = userInfo.username || (userInfo.id as string);

if (this.flags.json && this.flags.outputDataset) {
Expand Down
4 changes: 2 additions & 2 deletions src/commands/actors/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Flags } from '../../lib/command-framework/flags.js';
import { CommandExitCodes, LOCAL_CONFIG_PATH } from '../../lib/consts.js';
import { useActorConfig } from '../../lib/hooks/useActorConfig.js';
import { error, success } from '../../lib/outputs.js';
import { downloadZip, getLocalUserInfo, getLoggedClientOrThrow } from '../../lib/utils.js';
import { downloadZip, getCurrentUserInfo, getLoggedClientOrThrow } from '../../lib/utils.js';

const extractGitHubZip = async (url: string, directoryPath: string) => {
const zipFile = await downloadZip(url);
Expand Down Expand Up @@ -80,8 +80,8 @@ export class ActorsPullCommand extends ApifyCommand<typeof ActorsPullCommand> {

const { config: actorConfig } = actorConfigResult.unwrap();

const userInfo = await getLocalUserInfo();
const apifyClient = await getLoggedClientOrThrow();
const userInfo = await getCurrentUserInfo();

const isActorAutomaticallyDetected = !this.args.actorId;
const usernameOrId = userInfo.username || userInfo.id;
Expand Down
4 changes: 2 additions & 2 deletions src/commands/actors/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
createActZip,
createSourceFiles,
getActorLocalFilePaths,
getLocalUserInfo,
getCurrentUserInfo,
getLoggedClientOrThrow,
outputJobLog,
parseWaitForFinishMillis,
Expand Down Expand Up @@ -287,7 +287,7 @@ export class ActorsPushCommand extends ApifyCommand<typeof ActorsPushCommand> {

const { config: actorConfig } = actorConfigResult.unwrap();

const userInfo = await getLocalUserInfo();
const userInfo = await getCurrentUserInfo();
const isOrganizationLoggedIn = !!userInfo.organizationOwnerUserId;
const redirectUrlPart = isOrganizationLoggedIn ? `/organization/${userInfo.id}` : '';

Expand Down
7 changes: 3 additions & 4 deletions src/commands/actors/search.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { ApifyClient } from 'apify-client';
import chalk from 'chalk';

import { getAnonymousApifyClientOptions } from '../../lib/auth.js';
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { Args } from '../../lib/command-framework/args.js';
import { Flags } from '../../lib/command-framework/flags.js';
import { CompactMode, ResponsiveTable } from '../../lib/commands/responsive-table.js';
import { CommandExitCodes } from '../../lib/consts.js';
import { error, info, simpleLog } from '../../lib/outputs.js';
import { getApifyClientOptions, printJsonToStdout } from '../../lib/utils.js';
import { printJsonToStdout } from '../../lib/utils.js';

const pricingModelLabels: Record<string, string> = {
FREE: 'Free',
Expand Down Expand Up @@ -96,9 +97,7 @@ export class ActorsSearchCommand extends ApifyCommand<typeof ActorsSearchCommand
const { query } = this.args;
const { json, sortBy, category, username, pricingModel, limit, offset } = this.flags;

const clientOptions = await getApifyClientOptions();
delete clientOptions.token;
const client = new ApifyClient(clientOptions);
const client = new ApifyClient(getAnonymousApifyClientOptions());

let result;

Expand Down
4 changes: 2 additions & 2 deletions src/commands/actors/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { runActorOrTaskOnCloud, SharedRunOnCloudFlags } from '../../lib/commands
import { getConsoleUrl } from '../../lib/console-url.js';
import { LOCAL_CONFIG_PATH } from '../../lib/consts.js';
import { simpleLog } from '../../lib/outputs.js';
import { getLocalConfig, getLocalUserInfo, getLoggedClientOrThrow, printJsonToStdout } from '../../lib/utils.js';
import { getLocalConfig, getCurrentUserInfo, getLoggedClientOrThrow, printJsonToStdout } from '../../lib/utils.js';
import { ActorsCallCommand } from './call.js';

export class ActorsStartCommand extends ApifyCommand<typeof ActorsStartCommand> {
Expand Down Expand Up @@ -73,7 +73,7 @@ export class ActorsStartCommand extends ApifyCommand<typeof ActorsStartCommand>
const cwd = process.cwd();
const localConfig = getLocalConfig(cwd) || {};
const apifyClient = await getLoggedClientOrThrow();
const userInfo = await getLocalUserInfo();
const userInfo = await getCurrentUserInfo();
const usernameOrId = userInfo.username || (userInfo.id as string);

const {
Expand Down
19 changes: 14 additions & 5 deletions src/commands/auth/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ import chalk from 'chalk';
import computerName from 'computer-name';
import open from 'open';

import { APIFY_ENV_VARS } from '@apify/consts';
import { cryptoRandomObjectId } from '@apify/utilities';

import { getEnvToken, loginWithToken } from '../../lib/auth.js';
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { Flags } from '../../lib/command-framework/flags.js';
import { getConsoleIntegrationsUrl, getConsoleUrl } from '../../lib/console-url.js';
import { AUTH_FILE_PATH } from '../../lib/consts.js';
import { AUTH_FILE_PATH, CommandExitCodes } from '../../lib/consts.js';
import { getBackend } from '../../lib/credentials.js';
import { updateUserId } from '../../lib/hooks/telemetry/useTelemetryState.js';
import { useMaskedInput } from '../../lib/hooks/user-confirmations/useMaskedInput.js';
import { useSelectFromList } from '../../lib/hooks/user-confirmations/useSelectFromList.js';
import { createLocalApiServer } from '../../lib/local-api-server.js';
import { error, info, success } from '../../lib/outputs.js';
import { getLocalUserInfo, getLoggedClient, tildify } from '../../lib/utils.js';
import { error, info, success, warning } from '../../lib/outputs.js';
import { getLocalUserInfo, tildify } from '../../lib/utils.js';

// When logging in against a local Console instance (local platform development), validate the token
// against the local API rather than production.
Expand All @@ -28,7 +30,7 @@ const API_VERSION = 'v1';

const tryToLogin = async (token: string) => {
const apiBaseUrl = getConsoleUrl().includes('localhost') ? LOCAL_API_BASE_URL : undefined;
const isUserLogged = await getLoggedClient(token, apiBaseUrl);
const isUserLogged = await loginWithToken(token, apiBaseUrl);
const userInfo = await getLocalUserInfo();

if (isUserLogged) {
Expand All @@ -46,7 +48,14 @@ const tryToLogin = async (token: string) => {
success({
message: `You are logged in to Apify as ${userInfo.username || userInfo.id}. ${chalk.gray(`Your token is stored in ${tokenLocation}.`)}`,
});

if (getEnvToken()) {
warning({
message: `${APIFY_ENV_VARS.TOKEN} is set, so other commands keep using that token instead of this login. Unset it to use this account.`,
});
}
} else {
process.exitCode = CommandExitCodes.MissingAuth;
error({
message: 'Login to Apify failed, the provided API token is not valid.',
});
Expand Down Expand Up @@ -85,7 +94,7 @@ export class AuthLoginCommand extends ApifyCommand<typeof AuthLoginCommand> {
static override flags = {
token: Flags.string({
char: 't',
description: 'Apify API token.',
description: 'Apify API token to log in with and save. APIFY_TOKEN is deliberately ignored here.',
required: false,
}),
method: Flags.string({
Expand Down
11 changes: 10 additions & 1 deletion src/commands/auth/logout.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { APIFY_ENV_VARS } from '@apify/consts';

import { getEnvToken } from '../../lib/auth.js';
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { AUTH_FILE_PATH } from '../../lib/consts.js';
import { clearKeyringSecrets } from '../../lib/credentials.js';
import { rimrafPromised } from '../../lib/files.js';
import { updateUserId } from '../../lib/hooks/telemetry/useTelemetryState.js';
import { success } from '../../lib/outputs.js';
import { success, warning } from '../../lib/outputs.js';
import { tildify } from '../../lib/utils.js';

export class AuthLogoutCommand extends ApifyCommand<typeof AuthLogoutCommand> {
Expand Down Expand Up @@ -31,5 +34,11 @@ export class AuthLogoutCommand extends ApifyCommand<typeof AuthLogoutCommand> {
await updateUserId(null);

success({ message: 'You are logged out from your Apify account.' });

if (getEnvToken()) {
warning({
message: `${APIFY_ENV_VARS.TOKEN} is still set, so commands stay authenticated with that token.`,
});
}
}
}
14 changes: 8 additions & 6 deletions src/commands/auth/token.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { resolveAuth } from '../../lib/auth.js';
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { simpleLog } from '../../lib/outputs.js';
import { getLocalUserInfo, getLoggedClientOrThrow } from '../../lib/utils.js';
import { getLoggedClientOrThrow } from '../../lib/utils.js';

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

static override description = 'Prints the current API token for the Apify CLI.';
static override description =
'Prints the API token the CLI would use, resolved from APIFY_TOKEN or the stored login.';

static override examples = [
{
description: 'Print the stored API token to stdout (use with care — it is a secret).',
description: 'Print the resolved API token to stdout (use with care — it is a secret).',
command: 'apify auth token',
},
];
Expand All @@ -18,10 +20,10 @@ export class AuthTokenCommand extends ApifyCommand<typeof AuthTokenCommand> {

async run() {
await getLoggedClientOrThrow();
const userInfo = await getLocalUserInfo();
const auth = await resolveAuth();

if (userInfo.token) {
simpleLog({ message: userInfo.token, stdout: true });
if (auth) {
simpleLog({ message: auth.token, stdout: true });
}
}
}
5 changes: 2 additions & 3 deletions src/commands/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import { LANGUAGE_FLAG_CHOICES, USE_CASE_FLAG_CHOICES } from '../lib/templates/c
import {
downloadAndUnzip,
getJsonFileContent,
getLocalUserInfo,
getCurrentUserInfo,
getLoggedClientOrThrow,
isNodeVersionSupported,
isPythonVersionSupported,
Expand Down Expand Up @@ -317,8 +317,7 @@ export class CreateCommand extends ApifyCommand<typeof CreateCommand> {
? {
provider: gitProvider,
client: await getLoggedClientOrThrow(),
// Read after the client, which refreshes auth.json from the token the run resolved.
account: toGitAccount(await getLocalUserInfo()),
account: toGitAccount(await getCurrentUserInfo()),
// Omitted means on: the webhook is what makes a Git-sourced Actor rebuild on a push.
autoBuild: this.flags.autoBuild !== 'off',
...parseGitRepoFlag(gitRepo, actorName),
Expand Down
4 changes: 2 additions & 2 deletions src/commands/datasets/get-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { Args } from '../../lib/command-framework/args.js';
import { Flags } from '../../lib/command-framework/flags.js';
import { error, simpleLog } from '../../lib/outputs.js';
import { getLocalUserInfo, getLoggedClientOrThrow } from '../../lib/utils.js';
import { getCurrentUserInfo, getLoggedClientOrThrow } from '../../lib/utils.js';

const downloadFormatToContentType: Record<DownloadItemsFormat, string> = {
[DownloadItemsFormat.JSON]: 'application/json',
Expand Down Expand Up @@ -106,7 +106,7 @@ export class DatasetsGetItems extends ApifyCommand<typeof DatasetsGetItems> {
};
}

const info = await getLocalUserInfo();
const info = await getCurrentUserInfo();

const byName = await client
.dataset(`${info.username!}/${datasetId}`)
Expand Down
4 changes: 2 additions & 2 deletions src/commands/datasets/ls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Flags } from '../../lib/command-framework/flags.js';
import { prettyPrintBytes } from '../../lib/commands/pretty-print-bytes.js';
import { CompactMode, ResponsiveTable } from '../../lib/commands/responsive-table.js';
import { info, simpleLog } from '../../lib/outputs.js';
import { getLocalUserInfo, getLoggedClientOrThrow, printJsonToStdout, TimestampFormatter } from '../../lib/utils.js';
import { getCurrentUserInfo, getLoggedClientOrThrow, printJsonToStdout, TimestampFormatter } from '../../lib/utils.js';

const table = new ResponsiveTable({
allColumns: ['Dataset ID', 'Name', 'Items', 'Size', 'Created', 'Modified'],
Expand Down Expand Up @@ -58,7 +58,7 @@ export class DatasetsLsCommand extends ApifyCommand<typeof DatasetsLsCommand> {
const { desc, offset, limit, json, unnamed } = this.flags;

const client = await getLoggedClientOrThrow();
const user = await getLocalUserInfo();
const user = await getCurrentUserInfo();

const rawDatasetList = await client.datasets().list({ desc, offset, limit, unnamed });

Expand Down
24 changes: 14 additions & 10 deletions src/commands/info.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import chalk from 'chalk';

import { resolveAuth, TOKEN_SOURCE_LABELS } from '../lib/auth.js';
import { ApifyCommand } from '../lib/command-framework/apify-command.js';
import { getLocalUserInfo, getLoggedClientOrThrow } from '../lib/utils.js';
import { getCurrentUserInfo, getLoggedClientOrThrow } from '../lib/utils.js';

export class InfoCommand extends ApifyCommand<typeof InfoCommand> {
static override name = 'info' as const;
Expand All @@ -21,17 +22,20 @@ export class InfoCommand extends ApifyCommand<typeof InfoCommand> {

async run() {
await getLoggedClientOrThrow();
const info = await getLocalUserInfo();
const info = await getCurrentUserInfo();
const auth = await resolveAuth();

if (info) {
const niceInfo = {
username: info.username,
userId: info.id,
} as const;
const niceInfo: Record<string, string | undefined> = {
username: info.username,
userId: info.id,
};

for (const key of Object.keys(niceInfo) as (keyof typeof niceInfo)[]) {
console.log(`${chalk.gray(key)}: ${chalk.bold(niceInfo[key])}`);
}
if (auth) {
niceInfo['token source'] = TOKEN_SOURCE_LABELS[auth.source];
}

for (const key of Object.keys(niceInfo)) {
console.log(`${chalk.gray(key)}: ${chalk.bold(niceInfo[key])}`);
}
}
}
4 changes: 2 additions & 2 deletions src/commands/key-value-stores/ls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Flags } from '../../lib/command-framework/flags.js';
import { prettyPrintBytes } from '../../lib/commands/pretty-print-bytes.js';
import { CompactMode, ResponsiveTable } from '../../lib/commands/responsive-table.js';
import { info, simpleLog } from '../../lib/outputs.js';
import { getLocalUserInfo, getLoggedClientOrThrow, printJsonToStdout, TimestampFormatter } from '../../lib/utils.js';
import { getCurrentUserInfo, getLoggedClientOrThrow, printJsonToStdout, TimestampFormatter } from '../../lib/utils.js';

const table = new ResponsiveTable({
allColumns: ['Store ID', 'Name', 'Size', 'Created', 'Modified'],
Expand Down Expand Up @@ -55,7 +55,7 @@ export class KeyValueStoresLsCommand extends ApifyCommand<typeof KeyValueStoresL
const { desc, offset, limit, json, unnamed } = this.flags;

const client = await getLoggedClientOrThrow();
const user = await getLocalUserInfo();
const user = await getCurrentUserInfo();

const rawKvsList = await client.keyValueStores().list({ desc, offset, limit, unnamed });

Expand Down
Loading