Skip to content

Commit

Permalink
feat: auto-suggest and execute command on error
Browse files Browse the repository at this point in the history
  • Loading branch information
HugoRCD committed Mar 31, 2024
1 parent 7e71cb0 commit cac833e
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 33 deletions.
20 changes: 7 additions & 13 deletions apps/cli/src/commands/create.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineCommand, runCommand } from 'citty'
import { defineCommand } from 'citty'
import consola from 'consola'
import { createProject } from '../utils/projects.ts'
import link from './link.ts'
import { suggestLinkProject } from '../utils/suggest.ts'

export default defineCommand({
meta: {
Expand All @@ -21,19 +21,13 @@ export default defineCommand({
const name = ctx.args.name
consola.start(`Creating project ${ name }...`)
try {
await createProject(name)
let project = await createProject(name)
consola.success(`Project ${ name } created successfully!`)
const linkProject = await consola.prompt('Do you want to link the project? (y/n)', {
default: 'y',
type: 'confirm',
})
if (linkProject) {
await runCommand(link, { rawArgs: [name] }).then(() => {
consola.success('Project linked successfully!')
}).catch(() => {
consola.error('Failed to link the project')
})
const linkedProject = await suggestLinkProject(name)
if (linkedProject) {
project = linkedProject
}
return project
} catch (e) {
consola.error('Failed to create project')
}
Expand Down
7 changes: 6 additions & 1 deletion apps/cli/src/commands/link.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { defineCommand } from 'citty'
import { defineCommand, runCommand } from 'citty'
import { consola } from 'consola'
import { getProjectByName, getProjects, writeProjectConfig } from '../utils/projects.ts'
import { suggestCreateProject } from '../utils/suggest.ts'
import create from './create.ts'

export default defineCommand({
meta: {
Expand All @@ -23,6 +25,7 @@ export default defineCommand({
const project = await getProjectByName(name)
if (!project) {
consola.error(`Project with name ${name} not found`)
await suggestCreateProject(name)
return
}
writeProjectConfig(project)
Expand All @@ -33,6 +36,7 @@ export default defineCommand({
const projects = await getProjects()
if (!projects.length) {
consola.error('No projects found')
await suggestCreateProject(name)
return
}

Expand All @@ -53,6 +57,7 @@ export default defineCommand({

writeProjectConfig(project)
consola.success('Project linked successfully')
return project
} catch (e) {
consola.error('An error occurred while selecting the project')
}
Expand Down
14 changes: 10 additions & 4 deletions apps/cli/src/commands/open.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@ import { defineCommand } from 'citty'
import { consola } from 'consola'
import open from 'open'
import { getProjectId } from '../utils/projects.ts'
import { suggestLinkProjects } from '../utils/suggest.ts'

export default defineCommand({
meta: {
name: 'open',
description: 'Open the project in the browser',
},
setup() {
async setup() {
consola.info('Opening the project in the browser...')
const projectId = getProjectId()
let projectId = getProjectId()
if (!projectId) {
consola.error('No project linked run `shelve link` to link a project')
return
consola.error('The current project is not linked to a remote project')
const linkedProject = await suggestLinkProjects()
if (linkedProject) {
projectId = linkedProject.id
} else {
return
}
}
open(`https://shelve.hrcd.fr/app/project/${ projectId }`).then(r => r)
},
Expand Down
12 changes: 9 additions & 3 deletions apps/cli/src/commands/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineCommand } from 'citty'
import consola from 'consola'
import { createEnvFile, getProjectVariable } from '../utils/env.ts'
import { getProjectId } from '../utils/projects.ts'
import { suggestLinkProjects } from '../utils/suggest.ts'

export default defineCommand({
meta: {
Expand All @@ -18,10 +19,15 @@ export default defineCommand({
},
},
async run(ctx) {
const projectId = getProjectId()
let projectId = getProjectId()
if (!projectId) {
consola.error('Project is not linked run `shelve link` to link the project')
return
consola.error('The current project is not linked to a remote project')
const linkedProject = await suggestLinkProjects()
if (linkedProject) {
projectId = linkedProject.id
} else {
return
}
}
const variables = await getProjectVariable(projectId, ctx.args.env)
createEnvFile(variables)
Expand Down
12 changes: 9 additions & 3 deletions apps/cli/src/commands/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineCommand } from 'citty'
import consola from 'consola'
import { pushProjectVariable } from '../utils/env.ts'
import { getProjectId } from '../utils/projects.ts'
import { suggestLinkProjects } from '../utils/suggest.ts'

export default defineCommand({
meta: {
Expand All @@ -18,10 +19,15 @@ export default defineCommand({
},
},
async run(ctx) {
const projectId = getProjectId()
let projectId = getProjectId()
if (!projectId) {
consola.error('Project is not linked run `shelve link` to link the project')
return
consola.error('The current project is not linked to a remote project')
const linkedProject = await suggestLinkProjects()
if (linkedProject) {
projectId = linkedProject.id
} else {
return
}
}
await pushProjectVariable(projectId, ctx.args.env)
consola.success('Pushed successfully!')
Expand Down
8 changes: 5 additions & 3 deletions apps/cli/src/utils/connection.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ofetch } from 'ofetch'
import consola from 'consola'
import { loadUserConfig, writeUserConfig } from './config.ts'
import { suggestLogin } from './suggest.ts'

const SHELVE_API_URL = process.env.NODE_ENV === 'development' ? 'http://localhost:3000/api' : 'https://shelve.hrcd.fr/api'

Expand All @@ -12,10 +13,11 @@ export const $api: any = ofetch.create({
Cookie: `authToken=${loadUserConfig().authToken || ''}`
}
},
onResponseError(ctx) {
async onResponseError(ctx) {
if (ctx.response.status === 401) {
writeUserConfig({ ...loadUserConfig(), authToken: null })
consola.error('Authentication failed, please login again using `shelve login`')
writeUserConfig({...loadUserConfig(), authToken: null})
consola.error('Authentication failed')
await suggestLogin().then(r => r)
}
}
})
24 changes: 18 additions & 6 deletions apps/cli/src/utils/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'fs'
import type { Project } from '@shelve/types'
import consola from 'consola'
import { $api } from './connection.ts'
import { suggestLinkProject } from './suggest.ts'

export async function getProjects(): Promise<Project[]> {
return await $api('/project', {
Expand Down Expand Up @@ -79,11 +80,22 @@ export function addDotShelveToGitignore(): void {
}
}

export async function createProject(name: string): Promise<Project> {
return await $api('/project', {
method: 'POST',
body: {
name,
export async function createProject(name: string): Promise<Project | null> {
try {
let project = await $api('/project', {
method: 'POST',
body: {
name,
}
})
consola.success(`Project ${ name } created successfully!`)
const linkedProject = await suggestLinkProject(name)
if (linkedProject) {
project = linkedProject
}
})
return project
} catch (e) {
consola.error('Failed to create project')
return null
}
}
57 changes: 57 additions & 0 deletions apps/cli/src/utils/suggest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import consola from 'consola'
import { runCommand } from 'citty'
import type { Project } from '@shelve/types'
import link from '../commands/link.ts'
import login from '../commands/login.ts'
import { createProject } from './projects.ts'

export async function suggestCreateProject(name?: string): Promise<Project | null> {
const accept = await consola.prompt('Do you want to create a project? (y/n)', {
default: 'y',
type: 'confirm',
})
if (accept) {
if (name) {
return await createProject(name)
}
const projectName = await consola.prompt('Give your project a name', {
placeholder: 'my-project'
})
return await createProject(projectName)
}
return null
}

export async function suggestLinkProject(name: string): Promise<Project | null> {
const linkProject = await consola.prompt('Do you want to link the project? (y/n)', {
default: 'y',
type: 'confirm',
})
if (linkProject) {
const res = await runCommand(link, {rawArgs: ['--name', name]}) as { result: Project }
return res.result
}
return null
}

export async function suggestLinkProjects(): Promise<Project | null> {
const linkProject = await consola.prompt('Do you want to link a project? (y/n)', {
default: 'y',
type: 'confirm',
})
if (linkProject) {
const res = await runCommand(link, {rawArgs: []}) as { result: Project }
return res.result
}
return null
}

export async function suggestLogin(): Promise<void> {
const accept = await consola.prompt('Do you want to login? (y/n)', {
default: 'y',
type: 'confirm',
})
if (accept) {
await runCommand(login, {rawArgs: []})
}
}

0 comments on commit cac833e

Please sign in to comment.