Skip to content

Commit

Permalink
Merge pull request #183 from sasjs/issue-139
Browse files Browse the repository at this point in the history
feat(command-line): added command line parser utility
  • Loading branch information
YuryShkoda authored Oct 29, 2020
2 parents da4aece + cde1853 commit 1db4f5a
Show file tree
Hide file tree
Showing 2 changed files with 695 additions and 0 deletions.
184 changes: 184 additions & 0 deletions src/utils/command.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { displayResult } from './displayResult'

const showInvalidCommandMessage = () => {
displayResult(
{},
`Invalid command. Run 'sasjs help' to get the list of valid commands.`
)
}
const arrToObj = (arr) => arr.reduce((o, key) => ({ ...o, [key]: key }), {})

const initialCommands = arrToObj([
...new Set([
'create',
'web',
'build-DB',
'compile',
'build',
'compilebuild',
'deploy',
'compilebuilddeploy',
'servicepack',
'context',
'add',
'run',
'request',
'folder',
'job'
])
])

const initialFlags = arrToObj([
...new Set([
'target',
'source',
'template',
'source',
'datafile',
'configfile',
'wait',
'output',
'force'
])
])

const initialAliases = [
{ name: initialCommands['build-DB'], aliases: ['db'] },
{ name: initialCommands.compile, aliases: ['c'] },
{ name: initialCommands.build, aliases: ['b'] },
{ name: initialCommands.compilebuild, aliases: ['cb'] },
{ name: initialCommands.deploy, aliases: ['d'] },
{ name: initialCommands.compilebuilddeploy, aliases: ['cbd'] },
{ name: initialCommands.web, aliases: ['w'] },
{ name: initialCommands.add, aliases: ['a'] },
{ name: initialCommands.run, aliases: ['r'] },
{ name: initialCommands.request, aliases: ['rq'] }
]

const commandFlags = [
{
command: initialCommands.folder,
flags: [initialFlags.target, initialFlags.force]
},
{
command: initialCommands.context,
flags: [initialFlags.target, initialFlags.source]
},
{ command: initialCommands.create, flags: [initialFlags.template] },
{ command: initialCommands.web, flags: [initialFlags.target] },
{ command: initialCommands['build-DB'], flags: [initialFlags.target] },
{ command: initialCommands.compile, flags: [initialFlags.target] },
{ command: initialCommands.build, flags: [initialFlags.target] },
{ command: initialCommands.compilebuild, flags: [initialFlags.target] },
{ command: initialCommands.deploy, flags: [initialFlags.target] },
{
command: initialCommands.compilebuilddeploy,
flags: [initialFlags.target]
},
{
command: initialCommands.servicepack,
flags: [initialFlags.target, initialFlags.source]
},
{ command: initialCommands.run, flags: [initialFlags.target] },
{
command: initialCommands.request,
flags: [initialFlags.target, initialFlags.datafile, initialFlags.configfile]
},
{
command: initialCommands.job,
flags: [initialFlags.target, initialFlags.wait, initialFlags.output]
}
]

const flagsWithValue = [
initialFlags.target,
initialFlags.source,
initialFlags.template,
initialFlags.datafile,
initialFlags.configfile
]

export class Command {
values = []
flags = []

constructor(commandLine) {
if (typeof commandLine === 'string')
commandLine = commandLine.replace(/\s\s+/g, ' ').split(' ')

if (!Array.isArray(commandLine)) {
showInvalidCommandMessage()

return
}

const command = commandLine.shift()

if (Object.keys(initialCommands).includes(command)) {
this.name = command
} else {
const alias = initialAliases.find((alias) =>
alias.aliases.includes(command)
)

if (alias) this.name = alias.name
}

if (!this.name) {
showInvalidCommandMessage()

return
}

this.aliases = initialAliases.find((alias) => alias.name === this.name)
this.aliases = this.aliases ? this.aliases.aliases : null

this.supportedFlags = commandFlags.filter(
(commandFlag) => commandFlag.command === this.name
)[0].flags

for (let i = 0; i < commandLine.length; i++) {
if (/^-/.test(commandLine[i]) && this.supportedFlags) {
let flag = commandLine[i].split('-').join('')
const regExp = new RegExp(`^${flag}`)

flag = Object.keys(initialFlags)
.filter((f) => regExp.test(f))
.filter((f) => this.supportedFlags.includes(f))[0]

flag = new Flag(flag)

this.flags.push(flag)

if (flag.withValue) {
i++

const value = commandLine[i]

if (value) {
this.flags.find((f) => f.name === flag.name).setValue(value)
}
}
} else {
this.values.push(commandLine[i])
}
}
}
}

class Flag {
value = null

constructor(name) {
if (!name || typeof name !== 'string') throw 'Not valid flag name!'

this.name = name
this.longSyntax = '--' + name
this.shortSyntax = '-' + name[0]
this.withValue = flagsWithValue.includes(name)
}

setValue(value) {
this.value = value
}
}
Loading

0 comments on commit 1db4f5a

Please sign in to comment.