Skip to content

Commit

Permalink
feat(setup): add command for setting up CLI config
Browse files Browse the repository at this point in the history
  • Loading branch information
ulisesantana committed Dec 18, 2023
1 parent 0504232 commit e018853
Show file tree
Hide file tree
Showing 13 changed files with 421 additions and 180 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ EXAMPLES
$ track config
```

_See code: [src/commands/config/index.ts](https://github.com/ulisesantana/track/blob/v0.0.0/src/commands/config/index.ts)_
_See code: [src/commands/config/config.ts](https://github.com/ulisesantana/track/blob/v0.0.0/src/commands/config/index.ts)_

<!-- commandsstop -->

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
},
"bugs": "https://github.com/ulisesantana/track/issues",
"dependencies": {
"@inquirer/prompts": "^3.3.0",
"@inquirer/select": "^1.3.1",
"@oclif/core": "^3",
"@oclif/plugin-autocomplete": "^3.0.3",
"@oclif/plugin-help": "^5",
Expand Down Expand Up @@ -69,8 +71,8 @@
],
"topicSeparator": " ",
"topics": {
"hello": {
"description": "Say hello to the world and others"
"set": {
"description": "Set your config individually."
}
}
},
Expand Down
8 changes: 4 additions & 4 deletions src/commands/config/index.ts → src/commands/config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {Command} from '@oclif/core'
import path from "node:path";

import {GetConfigurationUseCase} from "../../application/cases";
import {configFilename} from "../../core";
import {FileSystemDataSource} from "../../infrastructure/data-sources";
import {ConfigurationRepositoryImplementation} from "../../infrastructure/repositories";
import {GetConfigurationUseCase} from "../application/cases";
import {configFilename} from "../core";
import {FileSystemDataSource} from "../infrastructure/data-sources";
import {ConfigurationRepositoryImplementation} from "../infrastructure/repositories";

export default class Config extends Command {
static description = 'Get your config for track CLI.'
Expand Down
98 changes: 0 additions & 98 deletions src/commands/config/set.ts

This file was deleted.

29 changes: 29 additions & 0 deletions src/commands/set/description.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {Command} from '@oclif/core'
import path from "node:path";

import {configFilename} from "../../core";
import {FileSystemDataSource} from "../../infrastructure/data-sources";
import {ConfigurationRepositoryImplementation} from "../../infrastructure/repositories";
import Setup from "../setup";

export default class SetDescription extends Command {
static description = 'Set your default time entry description for track CLI.'

static examples = [
'<%= config.bin %> <%= command.id %>',
]


public async run(): Promise<void> {
const configurationRepository = new ConfigurationRepositoryImplementation(new FileSystemDataSource(path.join(this.config.configDir, configFilename)))
try {
const defaultTimeEntry = await Setup.setDefaultTimeEntryDescription(configurationRepository)
this.log(`Your default time entry description has been set to: "${defaultTimeEntry}"`);
} catch (error) {
this.log(`There was an error trying to setting up your config. Detailed error:`)
this.log(`${error}`)
}
}


}
37 changes: 37 additions & 0 deletions src/commands/set/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {Command} from '@oclif/core'
import path from "node:path";

import {configFilename} from "../../core";
import {FileSystemDataSource, TogglApi, http} from "../../infrastructure/data-sources";
import {ConfigurationRepositoryImplementation} from "../../infrastructure/repositories";
import Setup from "../setup";

export default class SetProject extends Command {
static description = 'Setup your default project for track CLI.'

static examples = [
'<%= config.bin %> <%= command.id %>',
]

private static sortByName = (a: { name: string }, b: { name: string }) =>
a.name > b.name
? 1
: a.name < b.name
? -1
: 0

public async run(): Promise<void> {
const configurationRepository = new ConfigurationRepositoryImplementation(new FileSystemDataSource(path.join(this.config.configDir, configFilename)))
try {
const config = await configurationRepository.getAll()
const userInfo = await TogglApi.getUserInfo(config.apiToken, http)
const result = await Setup.setDefaultProject(userInfo, configurationRepository)
this.log(`Your default project has been set to: ${result}`);
} catch (error) {
this.log(`There was an error trying to setting up your config. Detailed error:`)
this.log(`${error}`)
}
}


}
28 changes: 28 additions & 0 deletions src/commands/set/token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {Command} from '@oclif/core'
import path from "node:path";

import {configFilename} from "../../core";
import {FileSystemDataSource} from "../../infrastructure/data-sources";
import {ConfigurationRepositoryImplementation} from "../../infrastructure/repositories";
import Setup from "../setup";

export default class SetToken extends Command {
static description = 'Setup your Toggl Track API token for track CLI.'

static examples = [
'<%= config.bin %> <%= command.id %>',
]

public async run(): Promise<void> {
const configurationRepository = new ConfigurationRepositoryImplementation(new FileSystemDataSource(path.join(this.config.configDir, configFilename)))
try {
await Setup.setApiKey(configurationRepository)
this.log('Your token has been updated.')
} catch (error) {
this.log(`There was an error trying to setting up your config. Detailed error:`)
this.log(`${error}`)
}
}


}
35 changes: 35 additions & 0 deletions src/commands/set/workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {Command} from '@oclif/core'
import path from "node:path";

import {configFilename} from "../../core";
import {FileSystemDataSource, TogglApi, http} from "../../infrastructure/data-sources";
import {ConfigurationRepositoryImplementation} from "../../infrastructure/repositories";
import Setup from "../setup";

export default class SetWorkspace extends Command {
static description = 'Setup your default workspace for track CLI.'

static examples = [
'<%= config.bin %> <%= command.id %>',
]

private static sortByName = (a: { name: string }, b: { name: string }) =>
a.name > b.name
? 1
: a.name < b.name
? -1
: 0

public async run(): Promise<void> {
const configurationRepository = new ConfigurationRepositoryImplementation(new FileSystemDataSource(path.join(this.config.configDir, configFilename)))
try {
const config = await configurationRepository.getAll()
const userInfo = await TogglApi.getUserInfo(config.apiToken, http)
const result = await Setup.setDefaultWorkspace(userInfo, configurationRepository)
this.log(`Your default workspace has been set to: ${result}`);
} catch (error) {
this.log(`There was an error trying to setting up your config. Detailed error:`)
this.log(`${error}`)
}
}
}
91 changes: 91 additions & 0 deletions src/commands/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable camelcase */
import {input, select} from '@inquirer/prompts';
import {Command} from '@oclif/core'
import path from "node:path";

import {configFilename} from "../core";
import {FileSystemDataSource, TogglApi, UserInfo, http} from "../infrastructure/data-sources";
import {ConfigurationRepositoryImplementation} from "../infrastructure/repositories";

export default class Setup extends Command {
static description = 'Setup your config for track CLI.'

static examples = [
'<%= config.bin %> <%= command.id %>',
]

private static sortByName = (a: { name: string }, b: { name: string }) =>
a.name > b.name
? 1
: a.name < b.name
? -1
: 0

static async setApiKey(configurationRepository: ConfigurationRepositoryImplementation) {
const apiKey = await input({message: 'Enter your name API Key:\n(For getting your Toggl API token you can go to https://track.toggl.com/profile and scroll to the bottom of your profile)\n'});
await configurationRepository.setApiToken(apiKey)
return apiKey;
}

static async setDefaultProject({clients, projects}: UserInfo, configurationRepository: ConfigurationRepositoryImplementation) {
const clientMap = new Map(clients.map(client => [client.id, client]))
const choices = projects
.filter(({active}) => active)
.sort(Setup.sortByName)
.map(project => ({
name: `${project.name} (${clientMap.get(project.client_id)?.name || 'No client'})`,
value: project.id
}))
const defaultProjectId = await select({
choices,
message: 'Select your default project',
});
await configurationRepository.setDefaultProjectId(defaultProjectId)
return choices.find(({value}) => value === defaultProjectId)?.name
}

static async setDefaultTimeEntryDescription(configurationRepository: ConfigurationRepositoryImplementation) {
const defaultTimeEntry = await input({
default: 'Working',
message: 'Enter your default time entry description.',
validate: Boolean
});
await configurationRepository.setDefaultTimeEntry(defaultTimeEntry)
return defaultTimeEntry
}

static async setDefaultWorkspace({default_workspace_id, workspaces}: UserInfo, configurationRepository: ConfigurationRepositoryImplementation) {
workspaces.sort(Setup.sortByName)
const defaultWorkspace = workspaces.find(({id}) => id === default_workspace_id)!
const choices = [defaultWorkspace, ...workspaces.filter(({id}) => id !== default_workspace_id)].map(workspace => ({
name: workspace.name,
value: workspace.id
}))
const defaultWorkspaceId = await select({
choices,
message: 'Select your default workspace',
});
await configurationRepository.setDefaultWorkspaceId(defaultWorkspaceId)
return choices.find(({value}) => value === defaultWorkspaceId)?.name
}

public async run(): Promise<void> {
const configurationRepository = new ConfigurationRepositoryImplementation(new FileSystemDataSource(path.join(this.config.configDir, configFilename)))
try {
// Add your API Key
const apiKey = await Setup.setApiKey(configurationRepository);
// Get user info
const userInfo = await TogglApi.getUserInfo(apiKey, http)
// Select your default workspace
await Setup.setDefaultWorkspace(userInfo, configurationRepository);
// Select your default project
await Setup.setDefaultProject(userInfo, configurationRepository);
// Add your default time entry description
await Setup.setDefaultTimeEntryDescription(configurationRepository);
this.log('Your config for track CLI has been setup.')
} catch (error) {
this.log(`There was an error trying to setting up your config. Detailed error:`)
this.log(`${error}`)
}
}
}
Loading

0 comments on commit e018853

Please sign in to comment.