import { defineCommand } from "../lib/command" import { globalOptions, globalOptionsSchema } from "../lib/global-options" import z from "zod" import { apiClient } from "../lib/api-client" import { accent, dimmed } from "../lib/io" import { clearSpinner, startSpinner, withSpinner } from "../lib/spinner" import { ORG_OPT, orgOptsSchema, output, promptableOption, REASONABLE_NAME_SCHEMA, safelyPromptTextWithValidation, sessionIntro, useOrganization, requireSession, ORG_OPTION_DESCRIPTIONS, } from "../utils" import { log } from "@clack/prompts" /** Arguments accepted by the project creation command. */ const createProjectOptsSchema = orgOptsSchema.extend({ name: promptableOption(REASONABLE_NAME_SCHEMA, "--name"), }) export const projectCreateCommand = defineCommand({ name: "create", description: "Create a new project", options: { ...globalOptions, ...ORG_OPT, name: { type: "string", short: "n", }, }, optionDescriptions: { ...ORG_OPTION_DESCRIPTIONS, name: "The name of the project", }, schema: globalOptionsSchema.extend(createProjectOptsSchema.shape), run: createProject, }) /** * Creates a project in the resolved organization. * * @param opts - Validated organization selector and optional project name. * @throws When the organization has reached its project limit. */ export async function createProject( opts: z.infer, ) { const session = await requireSession() output.normal(() => sessionIntro(session)) const org = await useOrganization(opts, { whenEmpty: "prompt-create" }) if ( !(await withSpinner("Checking project limit", () => apiClient.project.canCreate({ organizationId: org.id }), )) ) { throw new Error( `Project limit reached. Run \`automate org upgrade -o ${org.id}\` to create more projects.`, ) } let name = opts.name if (name == null) name = await promptName() startSpinner("Creating project") const project = await apiClient.project.create({ organizationId: org.id, name, }) clearSpinner() output .normal(() => log.success(`Created ${accent(project.name)} ${dimmed(project.id)}`), ) .json(project) } /** Prompts for and validates a project name. */ function promptName() { return safelyPromptTextWithValidation( { message: "What should we name the project?", placeholder: "My Awesome Project", }, REASONABLE_NAME_SCHEMA, "--name", ) }