diff --git a/src/subcommands/deploy.ts b/src/subcommands/deploy.ts index 0e77a062..433394c3 100644 --- a/src/subcommands/deploy.ts +++ b/src/subcommands/deploy.ts @@ -119,30 +119,48 @@ async function deploy(opts: DeployOpts): Promise { if (opts.dryRun) { wait("").start().info("Performing dry run of deployment"); } - const projectSpinner = wait("Fetching project information...").start(); + const projectInfoSpinner = wait( + `Fetching project '${opts.project}' information...`, + ).start(); const api = opts.token ? API.fromToken(opts.token) : API.withTokenProvisioner(TokenProvisioner); - - const project = await api.getProject(opts.project); + let projectIsEmpty = false; + let project = await api.getProject(opts.project); if (project === null) { - projectSpinner.fail("Project not found."); - Deno.exit(1); - } + projectInfoSpinner.stop(); + const projectCreationSpinner = wait( + `Project '${opts.project}' not found in any of the user's organizations. Creating...`, + ).start(); + try { + project = await api.createProject(opts.project); + } catch (e) { + error(e.message); + } + projectCreationSpinner.succeed(`Created new project '${opts.project}'.`); + wait({ text: "", indent: 3 }).start().info( + `You can configure the name, env vars, custom domains and more in https://dash.deno.com/projects/${project.name}/settings`, + ); + projectIsEmpty = true; + } else { + const deploymentsListing = await api.getDeployments(project.id); + if (deploymentsListing === null) { + projectInfoSpinner.fail("Project deployments details not found."); + Deno.exit(1); + } + const [projectDeployments, _pagination] = deploymentsListing!; + projectInfoSpinner.succeed(`Project: ${project.name}`); - const deploymentsListing = await api.getDeployments(project!.id); - if (deploymentsListing === null) { - projectSpinner.fail("Project deployments details not found."); - Deno.exit(1); + if (projectDeployments.length === 0) { + projectIsEmpty = true; + } } - const [projectDeployments, _pagination] = deploymentsListing!; - projectSpinner.succeed(`Project: ${project!.name}`); - if (projectDeployments.length === 0) { - wait("").start().info( - "Empty project detected, automatically pushing initial deployment to production (use --prod for further updates).", - ); + if (projectIsEmpty) { opts.prod = true; + wait({ text: "", indent: 3 }).start().info( + "The project does not have a deployment yet. Automatically pushing initial deployment to production (use --prod for further updates).", + ); } let url = opts.entrypoint; diff --git a/src/utils/api.ts b/src/utils/api.ts index ee468aef..9709a83d 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -159,6 +159,15 @@ export class API { } } + async createProject( + name?: string, + organizationId?: string, + envs?: Record, + ): Promise { + const body = { name, organizationId, envs }; + return await this.#requestJson(`/projects/`, { method: "POST", body }); + } + async getDeployments( projectId: string, ): Promise<[Deployment[], DeploymentsSummary] | null> {