Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 13 additions & 24 deletions src/commands/devicepreferences/create.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import inquirer from 'inquirer'
import { select } from '@inquirer/prompts'
import { type ArgumentsCamelCase, type Argv, type CommandModule } from 'yargs'

import { type DevicePreferenceCreate, type PreferenceType } from '@smartthings/core-sdk'
Expand All @@ -17,6 +17,7 @@ import {
import { userInputProcessor } from '../../lib/command/input-processor.js'
import { tableFieldDefinitions } from '../../lib/command/util/devicepreferences-util.js'
import {
booleanInput,
optionalIntegerInput,
optionalNumberInput,
optionalStringInput,
Expand Down Expand Up @@ -64,19 +65,13 @@ const getInputFromUser = async (): Promise<DevicePreferenceCreate> => {
const title = await stringInput('Preference title:')
const description = await optionalStringInput('Preference description:')

const required = (await inquirer.prompt({
type: 'confirm',
name: 'value',
message: 'Is the preference required?',
default: false,
})).value as boolean
const required = await booleanInput('Is the preference required?', { default: false })

const preferenceType = (await inquirer.prompt({
type: 'list',
name: 'preferenceType',
const preferenceTypeChoices: PreferenceType[] = ['integer', 'number', 'boolean', 'string', 'enumeration']
const preferenceType = await select({
message: 'Choose a type for your preference.',
choices: ['integer', 'number', 'boolean', 'string', 'enumeration'],
})).preferenceType as PreferenceType
choices: preferenceTypeChoices,
}) as PreferenceType

const base = {
name, title, description, required,
Expand Down Expand Up @@ -115,14 +110,12 @@ const getInputFromUser = async (): Promise<DevicePreferenceCreate> => {
}

if (preferenceType === 'boolean') {
const defaultValue = (await inquirer.prompt({
type: 'list',
name: 'defaultValue',
const defaultValue = await select({
message: 'Choose a default value.',
choices: [{ name: 'none', value: undefined },
{ name: 'true', value: true },
{ name: 'false', value: false }],
})).defaultValue as boolean | undefined
})
return {
...base, preferenceType, definition: {
default: defaultValue ?? undefined,
Expand All @@ -136,13 +129,11 @@ const getInputFromUser = async (): Promise<DevicePreferenceCreate> => {
'Optional maximum length.',
{ validate: numberValidateFn({ min: minLength || 1 }) },
)
const stringType = (await inquirer.prompt({
type: 'list',
name: 'stringType',
const stringType = await select({
message: 'Choose a type of string.',
choices: ['text', 'password', 'paragraph'],
default: 'text',
})).stringType as 'text' | 'password' | 'paragraph'
}) as 'text' | 'password' | 'paragraph'
const defaultValue = await optionalStringInput('Optional default value.', {
validate: input => {
if (minLength !== undefined && input.length < minLength) {
Expand Down Expand Up @@ -179,15 +170,13 @@ const getInputFromUser = async (): Promise<DevicePreferenceCreate> => {
}
} while (name)

const defaultValue = (await inquirer.prompt({
type: 'list',
name: 'defaultValue',
const defaultValue = await select({
message: 'Choose a default option.',
choices: [
{ name: 'none', value: undefined },
...Object.entries(options).map(([name, value]) => ({ name: `${value} (${name})`, value: name }))],
default: undefined,
})).defaultValue as 'text' | 'password' | 'paragraph'
})

return {
...base, preferenceType, definition: {
Expand Down
65 changes: 27 additions & 38 deletions src/lib/command/util/deviceprofiles-create.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import inquirer from 'inquirer'
import { input, select } from '@inquirer/prompts'

import {
type DeviceProfile,
Expand All @@ -8,11 +8,12 @@ import {
type SmartThingsClient,
} from '@smartthings/core-sdk'

import { optionalStringInput, stringInput } from '../../user-query.js'
import { fatalError } from '../../util.js'
import { APICommand } from '../api-command.js'
import { chooseCapabilityFiltered } from './capabilities-choose.js'
import { type CapabilityId } from './capabilities-util.js'
import { cleanupForCreate, cleanupForUpdate, DeviceDefinitionRequest } from './deviceprofiles-util.js'
import { APICommand } from '../api-command.js'
import { fatalError } from '../../util.js'


const capabilitiesWithoutPresentations = ['healthCheck', 'execute']
Expand Down Expand Up @@ -128,18 +129,20 @@ export const capabilityDefined = async (client: SmartThingsClient, idStr: string
}
}

export const promptAndAddCapability = async (command: APICommand, deviceProfile: DeviceProfileRequest, componentId: string, prompt = 'Capability ID'): Promise<CapabilityId> => {
export const promptAndAddCapability = async (
command: APICommand,
deviceProfile: DeviceProfileRequest,
componentId: string,
prompt = 'Capability Id',
): Promise<CapabilityId> => {
let capabilityId: CapabilityId = { id: '', version: 0 }
const idStr = (await inquirer.prompt({
type: 'input',
name: 'id',
const idStr = await input({
message: `${prompt} (type ? for a list):`,
validate: async (input) => {
return (input.endsWith('?') || input === '' || await capabilityDefined(command.client, input))
validate: async (input) =>
(input.endsWith('?') || input === '' || await capabilityDefined(command.client, input))
? true
: `Invalid ID "${input}". Please enter a valid capability ID or ? for a list of available capabilities.`
},
})).id
: `Invalid Id "${input}". Please enter a valid capability Id or ? for a list of available capabilities.`,
})

if (idStr) {
if (idStr.endsWith('?')) {
Expand All @@ -162,34 +165,25 @@ export const promptAndAddCapability = async (command: APICommand, deviceProfile:
return capabilityId
}

const componentRegExp = new RegExp(/^[0-9a-zA-Z]{1,100}$/)
export const promptAndAddComponent = async (deviceProfile: DeviceProfileRequest, previousComponentId: string): Promise<string> => {
const components = deviceProfile.components || []
let componentId: string = (await inquirer.prompt({
type: 'input',
name: 'componentId',
message: 'ComponentId ID: ',
validate: (input) => {
return (new RegExp(/^[0-9a-zA-Z]{1,100}$/).test(input) && !components.find(it => it.id === input)) || 'Invalid component name'
},
})).componentId
const componentId = await optionalStringInput('Component Id:', {
validate: input => (componentRegExp.test(input) && !components.find(it => it.id === input)) || 'Invalid component name',
})

if (componentId) {
components.push({ id: componentId, capabilities: [] })
} else {
componentId = previousComponentId
return componentId
}
return componentId
return previousComponentId
}

const profileNameRegExp = new RegExp(/^(?!\s)[-_!.~'() *0-9a-zA-Z]{1,100}(?<!\s)$/)
export const getInputFromUser = async (command: APICommand): Promise<DeviceProfileRequest> => {
const name = (await inquirer.prompt({
type: 'input',
name: 'deviceProfileName',
message: 'Device Profile Name:',
validate: (input: string) => {
return new RegExp(/^(?!\s)[-_!.~'() *0-9a-zA-Z]{1,100}(?<!\s)$/).test(input) || 'Invalid device profile name'
},
})).deviceProfileName
const name = await stringInput('Device Profile Name:', {
validate: (input: string) => profileNameRegExp.test(input) || 'Invalid device profile name',
})

const deviceProfile: DeviceProfileRequest = {
name,
Expand All @@ -203,7 +197,7 @@ export const getInputFromUser = async (command: APICommand): Promise<DeviceProfi

let primaryCapabilityId: CapabilityId
do {
primaryCapabilityId = await promptAndAddCapability(command, deviceProfile, 'main', 'Primary capability ID')
primaryCapabilityId = await promptAndAddCapability(command, deviceProfile, 'main', 'Primary capability Id')
} while (!primaryCapabilityId.id)

const enum Action {
Expand All @@ -216,12 +210,7 @@ export const getInputFromUser = async (command: APICommand): Promise<DeviceProfi
let componentId = 'main'
const choices = [Action.ADD_CAPABILITY, Action.ADD_COMPONENT, Action.FINISH]
do {
action = (await inquirer.prompt({
type: 'list',
name: 'action',
message: 'Select an action...',
choices,
})).action
action = await select({ message: 'Select an action...', choices })

if (action === Action.ADD_CAPABILITY) {
await promptAndAddCapability(command, deviceProfile, componentId)
Expand Down