diff --git a/packages/cli/src/commands/deviceprofiles/presentation.ts b/packages/cli/src/commands/deviceprofiles/presentation.ts deleted file mode 100644 index 6fa98e89..00000000 --- a/packages/cli/src/commands/deviceprofiles/presentation.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Errors } from '@oclif/core' - -import { APIOrganizationCommand, formatAndWriteItem } from '@smartthings/cli-lib' - -import { buildTableOutput } from '../presentation.js' -import { chooseDeviceProfile } from '../../lib/commands/deviceprofiles-util.js' - - -export default class DeviceProfilePresentationCommand extends APIOrganizationCommand { - static description = 'get the presentation associated with a device profile' + - this.apiDocsURL('getDeviceProfile', 'getDevicePresentation') - - static flags = { - ...APIOrganizationCommand.flags, - ...formatAndWriteItem.flags, - } - - static args = [{ - name: 'id', - description: 'device profile UUID or the number of the profile from list', - }] - - static examples = [ - '$ smartthings deviceprofiles:presentation fd4adb7f-4a23-4134-9b39-05ed889a03cf', - '$ smartthings deviceprofiles:presentation fd4adb7f-4a23-4134-9b39-05ed889a03cf --language=ko', - '$ smartthings deviceprofiles:presentation fd4adb7f-4a23-4134-9b39-05ed889a03cf --language=NONE', - '', - 'Specifying only the presentationId defaults to the "SmartThingsCommunity" manufacturer', - 'name and the language set for the computer\'s operating system. The language can be', - 'overridden by specifying an ISO language code. If "NONE" is specified for the language', - 'flag then no language header is specified in the API request', - ] - - async run(): Promise { - const id = await chooseDeviceProfile(this, this.args.id, { allowIndex: true }) - - const profile = await this.client.deviceProfiles.get(id) - if (!profile.metadata) { - throw new Errors.CLIError('No presentation defined for device profile') - } - - const presentation = await this.client.presentation.getPresentation(profile.metadata.vid, profile.metadata.mnmn) - await formatAndWriteItem(this, { buildTableOutput: data => buildTableOutput(this.tableGenerator, data) }, presentation) - } -} diff --git a/src/commands/deviceprofiles/presentation.ts b/src/commands/deviceprofiles/presentation.ts new file mode 100644 index 00000000..1aaa7c2c --- /dev/null +++ b/src/commands/deviceprofiles/presentation.ts @@ -0,0 +1,77 @@ +import { type ArgumentsCamelCase, type Argv, type CommandModule } from 'yargs' + +import { apiDocsURL } from '../../lib/command/api-command.js' +import { fatalError } from '../../lib/util.js' +import { + apiOrganizationCommand, + apiOrganizationCommandBuilder, + type APIOrganizationCommandFlags, +} from '../../lib/command/api-organization-command.js' +import { + formatAndWriteItem, + formatAndWriteItemBuilder, + type FormatAndWriteItemFlags, +} from '../../lib/command/format.js' +import { chooseDeviceProfile } from '../../lib/command/util/deviceprofiles-choose.js' +import { buildTableOutput } from '../../lib/command/util/presentation-table.js' + + +export type CommandArgs = + & APIOrganizationCommandFlags + & FormatAndWriteItemFlags + & { + idOrIndex?: string + } + +const command = 'deviceprofiles:presentation [id-or-index]' + +const describe = 'get the presentation associated with a device profile' + +export const builder = (yargs: Argv): Argv => + formatAndWriteItemBuilder(apiOrganizationCommandBuilder(yargs)) + .positional('id-or-index', { describe: 'device profile id or number from list', type: 'string' }) + .example([ + [ + '$0 deviceprofiles:presentation', + 'prompt for a device profile and display its presentation information', + ], + [ + '$0 deviceprofiles:presentation 2', + 'display presentation information for the second device profile listed when running' + + ' "smartthings deviceprofiles"', + ], + [ + '$0 deviceprofiles:presentation fd4adb7f-4a23-4134-9b39-05ed889a03cf', + 'display presentation information for the specified device profile', + ], + [ + '$0 deviceprofiles:presentation fd4adb7f-4a23-4134-9b39-05ed889a03cf --language ko', + 'display presentation information for the specified device profile and language', + ], + ]) + .epilog('Specifying only the presentationId defaults to the language set for the' + + ' computer\'s operating system. The language can be overridden by specifying an ISO' + + ' language code. If "NONE" is specified for the language' + + 'flag then no language header is specified in the API request\n\n' + + apiDocsURL('getDeviceProfile', 'getDevicePresentation')) + +const handler = async (argv: ArgumentsCamelCase): Promise => { + const command = await apiOrganizationCommand(argv) + + const id = await chooseDeviceProfile(command, argv.idOrIndex, { allowIndex: true }) + + const profile = await command.client.deviceProfiles.get(id) + if (!profile.metadata) { + return fatalError('No presentation defined for device profile') + } + + const presentation = await command.client.presentation.getPresentation(profile.metadata.vid, profile.metadata.mnmn) + await formatAndWriteItem( + command, + { buildTableOutput: data => buildTableOutput(command.tableGenerator, data) }, + presentation, + ) +} + +const cmd: CommandModule = { command, describe, builder, handler } +export default cmd diff --git a/src/commands/index.ts b/src/commands/index.ts index 45737617..05c7e2c5 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -33,6 +33,7 @@ import devicepreferencesTranslationsCreateCommand from './devicepreferences/tran import devicepreferencesTranslationsUpdateCommand from './devicepreferences/translations/update.js' import deviceprofilesCommand from './deviceprofiles.js' import deviceprofilesCreateCommand from './deviceprofiles/create.js' +import deviceprofilesPresentationCommand from './deviceprofiles/presentation.js' import deviceprofilesPublishCommand from './deviceprofiles/publish.js' import deviceprofilesViewCommand from './deviceprofiles/view.js' import deviceprofilesTranslations from './deviceprofiles/translations.js' @@ -148,6 +149,7 @@ export const commands: CommandModule[] = [ devicepreferencesTranslationsUpdateCommand, deviceprofilesCommand, deviceprofilesCreateCommand, + deviceprofilesPresentationCommand, deviceprofilesPublishCommand, deviceprofilesViewCommand, deviceprofilesTranslations, diff --git a/src/lib/validate-util.ts b/src/lib/validate-util.ts index 0bf7dc55..5228eb0a 100644 --- a/src/lib/validate-util.ts +++ b/src/lib/validate-util.ts @@ -1,6 +1,9 @@ import { type ValidateFunction } from './user-query.js' +// TODO: it would be simpler and more flexible if we allowed min/max alongside regex here. +// Even though min/max can be specified in the regex, we can give the user better error messages +// if we include them specifically. export type RegExStringValidationOptions = { regex: string | RegExp