Skip to content
Merged
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
69 changes: 45 additions & 24 deletions src/application/cli/command/apiKey/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {ErrorReason, HelpfulError} from '@/application/error';
import {UserApi} from '@/application/api/user';
import {FileSystem} from '@/application/fs/fileSystem';
import {WorkspaceApi} from '@/application/api/workspace';
import {ProjectConfiguration} from '@/application/project/configuration/projectConfiguration';

export type CreateApiKeyInput = {
name?: ApiKey['name'],
Expand Down Expand Up @@ -43,31 +44,9 @@ export class CreateApiKeyCommand implements Command<CreateApiKeyInput> {
const {configurationManager, api, fileSystem, io} = this.config;
const configuration = await configurationManager.load();

const environment = input.environment ?? await io.input.select({
message: 'Which environment?',
options: ApplicationEnvironment.all()
.map(
value => ({
label: ApplicationEnvironment.getLabel(value),
value: value,
}),
),
});

const applicationSlug = environment === ApplicationEnvironment.PRODUCTION
? configuration.applications.production
: configuration.applications.development;

if (applicationSlug === undefined) {
throw new HelpfulError(
`No ${ApplicationEnvironment.getLabel(environment).toLowerCase()} application `
+ 'found in the project configuration.',
{reason: ErrorReason.INVALID_INPUT},
);
}

const notifier = io.output.notify('Loading information');

const environment = await this.getEnvironment(configuration, input.environment);
const applicationSlug = this.getApplicationSlug(configuration, environment);
const defaultName = input.name ?? `${(await api.user.getUser()).username} (CLI)`;
const features = await api.workspace.getFeatures({
organizationSlug: configuration.organization,
Expand Down Expand Up @@ -131,4 +110,46 @@ export class CreateApiKeyCommand implements Command<CreateApiKeyInput> {

io.output.confirm(`API key saved to \`${fileName}\``);
}

private getApplicationSlug(configuration: ProjectConfiguration, environment: ApplicationEnvironment): string {
const application = environment === ApplicationEnvironment.PRODUCTION
? configuration.applications.production
: configuration.applications.development;

if (application === undefined) {
throw new HelpfulError(
`No ${ApplicationEnvironment.getLabel(environment).toLowerCase()} application `
+ 'found in the project configuration.',
{reason: ErrorReason.INVALID_INPUT},
);
}

return application;
}

private getEnvironment(
configuration: ProjectConfiguration,
environment?: ApplicationEnvironment,
): Promise<ApplicationEnvironment> {
if (environment !== undefined) {
return Promise.resolve(environment);
}

Copy link

Copilot AI Jul 2, 2025

Choose a reason for hiding this comment

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

If both production and development are undefined, this code will default to DEVELOPMENT and only later throw—consider adding a guard here to surface a clear error when no environments are configured.

Suggested change
if (configuration.applications.production === undefined
&& configuration.applications.development === undefined) {
throw new HelpfulError(
'No environments are configured in the project. Please configure at least one environment.',
{reason: ErrorReason.INVALID_INPUT},
);
}

Copilot uses AI. Check for mistakes.
if (configuration.applications.production === undefined) {
return Promise.resolve(ApplicationEnvironment.DEVELOPMENT);
}

const {io: {input}} = this.config;

return input.select({
Comment on lines +130 to +144
Copy link

Copilot AI Jul 2, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider declaring this method as async rather than returning Promise.resolve(...), which improves readability and consistency with its asynchronous usage.

Suggested change
private getEnvironment(
configuration: ProjectConfiguration,
environment?: ApplicationEnvironment,
): Promise<ApplicationEnvironment> {
if (environment !== undefined) {
return Promise.resolve(environment);
}
if (configuration.applications.production === undefined) {
return Promise.resolve(ApplicationEnvironment.DEVELOPMENT);
}
const {io: {input}} = this.config;
return input.select({
private async getEnvironment(
configuration: ProjectConfiguration,
environment?: ApplicationEnvironment,
): Promise<ApplicationEnvironment> {
if (environment !== undefined) {
return environment;
}
if (configuration.applications.production === undefined) {
return ApplicationEnvironment.DEVELOPMENT;
}
const {io: {input}} = this.config;
return await input.select({

Copilot uses AI. Check for mistakes.
message: 'Select environment',
options: ApplicationEnvironment.all()
.map(
value => ({
label: ApplicationEnvironment.getLabel(value),
value: value,
}),
),
});
}
}