Skip to content

Commit

Permalink
feat(cli): Improved the DX for list profile (#334)
Browse files Browse the repository at this point in the history
Co-authored-by: Rajdip Bhattacharya <agentR47@gmail.com>
  • Loading branch information
kriptonian1 and rajdip-b committed Jul 29, 2024
1 parent d6aba27 commit 6bff496
Show file tree
Hide file tree
Showing 22 changed files with 8,901 additions and 2,113 deletions.
9 changes: 7 additions & 2 deletions apps/cli/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ module.exports = {
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended'
'plugin:prettier/recommended',
'standard-with-typescript'
],
root: true,
env: {
Expand All @@ -21,6 +22,10 @@ module.exports = {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': ['warn']
'@typescript-eslint/no-unused-vars': ['warn'],
'@typescript-eslint/space-before-function-paren': 'off',
'@typescript-eslint/strict-boolean-expressions': 'off',
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'space-before-function-paren': 'off',
}
}
28 changes: 28 additions & 0 deletions apps/cli/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"dynamicImport": true,
"decorators": false
},
"transform": null,
"target": "es2016",
"loose": false,
"externalHelpers": false,
"keepClassNames": false,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"module": {
"type": "commonjs",
"strict": false,
"strictMode": false,
"noInterop": false,
"lazy": false
},
"minify": true
}
19 changes: 14 additions & 5 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,32 @@
"main": "index.js",
"type": "commonjs",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"start": "node dist/index.js"
"build": "swc src --out-dir dist",
"start": "node dist/src/index.js",
"dev": "pnpm build && node dist/src/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@clack/core": "^0.3.4",
"@clack/prompts": "^0.7.0",
"@types/figlet": "^1.5.8",
"chalk": "^4.1.2",
"cli-table": "^0.3.11",
"colors": "^1.4.0",
"commander": "^12.1.0",
"figlet": "^1.7.0",
"fs": "0.0.1-security",
"nodemon": "^3.1.4",
"socket.io-client": "^4.7.5",
"typescript": "^5.5.2"
},
"devDependencies": {}
"devDependencies": {
"@swc/cli": "^0.4.0",
"@swc/core": "^1.6.13",
"@types/cli-table": "^0.3.4",
"@types/figlet": "^1.5.8",
"@types/node": "^20.14.10",
"eslint-config-standard-with-typescript": "^43.0.1"
}
}
18 changes: 10 additions & 8 deletions apps/cli/src/commands/base.command.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Command } from 'commander'
import {
import type {
CommandActionData,
CommandArgument,
CommandOption
} from '../types/command/command.types'
import { fetchProfileConfig } from '../util/configuration'
import Logger from '../util/logger'
import { getDefaultProfile } from '../util/profile'
} from '@/types/command/command.types'
import { fetchProfileConfig } from '@/util/configuration'
import Logger from '@/util/logger'
import { getDefaultProfile } from '@/util/profile'
import type { Command } from 'commander'

/**
* The base class for all commands. All commands should extend this class.
Expand Down Expand Up @@ -38,7 +38,7 @@ export default abstract class BaseCommand {
const args: string[] = data.slice(0, argsCount)
await this.action({ args, options: commandOptions })
} catch (error) {
Logger.error(error.message)
Logger.error(error.message as string)
process.exit(1)
}
})
Expand All @@ -54,7 +54,9 @@ export default abstract class BaseCommand {
command.argument(argument.name, argument.description)
)

this.getSubCommands().forEach((subCommand) => subCommand.prepare(command))
this.getSubCommands().forEach((subCommand) => {
subCommand.prepare(command)
})
}

/**
Expand Down
15 changes: 7 additions & 8 deletions apps/cli/src/commands/init.command.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {
writePrivateKeyConfig,
writeProjectRootConfig
} from '../util/configuration'
import {
import type {
CommandActionData,
CommandOption
} from '../types/command/command.types'
} from '@/types/command/command.types'
import BaseCommand from './base.command'
import { intro, text, confirm, outro } from '@clack/prompts'
import { existsSync } from 'fs'
import {
writePrivateKeyConfig,
writeProjectRootConfig
} from '@/util/configuration'

export default class InitCommand extends BaseCommand {
getOptions(): CommandOption[] {
Expand Down Expand Up @@ -98,12 +98,11 @@ export default class InitCommand extends BaseCommand {
private async checkOverwriteExistingProjectConfig(): Promise<void> {
if (existsSync('./keyshade.json')) {
const overwrite = await confirm({
message: `Configuration already exists. Do you want to overwrite it?`
message: 'Configuration already exists. Do you want to overwrite it?'
})

if (!overwrite) {
outro('Configuration cancelled')
return
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions apps/cli/src/commands/profile.command.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import BaseCommand from './base.command'
import CreateProfile from './profile/create.profile'
import DeleteProfile from './profile/delete.profile'
import ListProfile from './profile/list.profile'
import UpdateProfile from './profile/update.profile'
import UseProfile from './profile/use.profile'
import BaseCommand from '@/commands/base.command'
import CreateProfile from '@/commands/profile/create.profile'
import DeleteProfile from '@/commands/profile/delete.profile'
import ListProfile from '@/commands/profile/list.profile'
import UpdateProfile from '@/commands/profile/update.profile'
import UseProfile from '@/commands/profile/use.profile'

export default class ProfileCommand extends BaseCommand {
getName(): string {
Expand Down
22 changes: 9 additions & 13 deletions apps/cli/src/commands/profile/create.profile.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import BaseCommand from '../base.command'
import {
import BaseCommand from '@/commands/base.command'
import type {
CommandActionData,
CommandOption
} from '../../types/command/command.types'
import { API_BASE_URL } from '../../util/constants'
} from '@/types/command/command.types'
import type { ProfileConfig } from '@/types/index.types'
import { fetchProfileConfig, writeProfileConfig } from '@/util/configuration'
import { API_BASE_URL } from '@/util/constants'
import { intro, outro, confirm, spinner, text } from '@clack/prompts'
import {
fetchProfileConfig,
writeProfileConfig
} from '../../util/configuration'
import { ProfileConfig } from '../../types/index.types'

export default class CreateProfile extends BaseCommand {
private profiles: ProfileConfig
Expand Down Expand Up @@ -85,23 +82,22 @@ export default class CreateProfile extends BaseCommand {

if (!apiKey) {
apiKey = await text({
message: 'Enter the private key for the profile',
message: 'Enter the API key for the profile',
placeholder: 'ks_************'
})
}

return { name, apiKey, baseUrl, setDefault }
}

private async checkOverwriteExistingProfile(name: string): Promise<boolean> {
if (!!this.profiles[name]) {
private async checkOverwriteExistingProfile(name: string): Promise<void> {
if (this.profiles[name]) {
const overwrite = await confirm({
message: `Profile ${name} already exists. Do you want to overwrite it?`
})

if (!overwrite) {
outro('Profile creation cancelled')
return
}
}
}
Expand Down
18 changes: 7 additions & 11 deletions apps/cli/src/commands/profile/delete.profile.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import {
import BaseCommand from '@/commands/base.command'
import { confirm, spinner } from '@clack/prompts'
import { checkIsDefaultProfile, checkProfileExists } from '@/util/profile'
import type {
CommandActionData,
CommandArgument
} from 'src/types/command/command.types'
import BaseCommand from '../base.command'
import { confirm, spinner } from '@clack/prompts'
import {
fetchProfileConfig,
writeProfileConfig
} from '../../util/configuration'
import { ProfileConfig } from 'src/types/index.types'
import { checkIsDefaultProfile, checkProfileExists } from 'src/util/profile'
} from '@/types/command/command.types'
import { fetchProfileConfig, writeProfileConfig } from '@/util/configuration'
import type { ProfileConfig } from '@/types/index.types'

export default class DeleteProfile extends BaseCommand {
profiles: ProfileConfig
Expand Down Expand Up @@ -53,7 +50,6 @@ export default class DeleteProfile extends BaseCommand {

if (!choice) {
s.stop(`Profile ${profile} not deleted`)
return
}
}
}
Expand Down
87 changes: 66 additions & 21 deletions apps/cli/src/commands/profile/list.profile.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import {
import BaseCommand from '@/commands/base.command'
import { getDefaultProfile } from '@/util/profile'
import type { ProfileConfig } from '@/types/index.types'
import { fetchProfileConfig } from '@/util/configuration'
import type {
CommandActionData,
CommandOption
} from 'src/types/command/command.types'
import BaseCommand from '../base.command'
import { fetchProfileConfig } from '../../util/configuration'
import Logger from '../../util/logger'
import { ProfileConfig } from '../../types/index.types'
import { getDefaultProfile } from '../../util/profile'
} from '@/types/command/command.types'

// eslint-disable-next-line @typescript-eslint/no-var-requires
const Table = require('cli-table')
// eslint-disable-next-line @typescript-eslint/no-var-requires
const colors = require('colors/safe')

export default class ListProfile extends BaseCommand {
private profiles: ProfileConfig
Expand All @@ -32,31 +36,72 @@ export default class ListProfile extends BaseCommand {

async action({ options }: CommandActionData): Promise<void> {
const { verbose } = options

this.profiles = await fetchProfileConfig()
const defaultProfile = getDefaultProfile(this.profiles)
delete this.profiles.default

Logger.log('Profiles:')
Object.keys(this.profiles).forEach((profile) =>
this.printProfile(profile, defaultProfile, verbose)
)
this.printProfile(this.profiles, defaultProfile, verbose as boolean)
}

/**
* Prints the profile information in a formatted table.
*
* @param profiles - The profile configuration object.
* @param defaultProfile - The name of the default profile.
* @param verbose - A boolean indicating whether to display additional information.
*/
private printProfile(
profile: string,
profiles: ProfileConfig,
defaultProfile: string,
verbose: boolean
): void {
if (defaultProfile === profile) {
Logger.log(`- ${profile} (default)`)
} else {
Logger.log(`- ${profile}`)
}
) {
const table = new Table({
chars: {
top: '═',
'top-mid': '╤',
'top-left': '╔',
'top-right': '╗',
bottom: '═',
'bottom-mid': '╧',
'bottom-left': '╚',
'bottom-right': '╝',
left: '║',
'left-mid': '╟',
mid: '─',
'mid-mid': '┼',
right: '║',
'right-mid': '╢',
middle: '│'
}
})

if (verbose) {
Logger.log(` - API Key: ${this.profiles[profile].apiKey}`)
Logger.log(` - Base URL: ${this.profiles[profile].baseUrl}`)
const profileList = []
Object.keys(profiles).forEach((profile) => {
profileList.push([
`${defaultProfile === profile ? `${profile} ${colors.dim('(default)')}` : profile}`,
`${profiles[profile].apiKey}`,
`${profiles[profile].baseUrl}`
])
})
table.push(
[
colors.cyan.bold('Profile'),
colors.cyan.bold('API Key'),
colors.cyan.bold('Base URL')
],
...profileList
)
} else {
const profileList = []
Object.keys(profiles).forEach((profile) => {
profileList.push([
`${defaultProfile === profile ? `${profile} ${colors.dim('(default)')}` : profile}`
])
})
table.push([colors.cyan.bold('Profile')], ...profileList)
}

console.log(table.toString())
}
}
Loading

0 comments on commit 6bff496

Please sign in to comment.