Skip to content

Commit

Permalink
fix: fix rules lookup without location id and functional refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
rossiam committed Jan 13, 2021
1 parent 4cca996 commit bfa67b6
Show file tree
Hide file tree
Showing 16 changed files with 327 additions and 291 deletions.
143 changes: 71 additions & 72 deletions packages/cli/README.md

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions packages/cli/src/commands/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { flags } from '@oclif/command'

import { App, AppType, AppClassification, AppListOptions } from '@smartthings/core-sdk'

import { ListingOutputAPICommand, TableFieldDefinition } from '@smartthings/cli-lib'
import { APICommand, outputListing, TableFieldDefinition } from '@smartthings/cli-lib'


const isWebhookSmartApp = (app: App): boolean => !!app.webhookSmartApp
Expand Down Expand Up @@ -35,11 +35,12 @@ export const tableFieldDefinitions: TableFieldDefinition<App>[] = [
{ prop: 'installMetadata.certified', include: app => app.installMetadata?.certified !== undefined },
]

export default class AppsList extends ListingOutputAPICommand<App, App> {
export default class AppsList extends APICommand {
static description = 'get a specific app or a list of apps'

static flags = {
...ListingOutputAPICommand.flags,
...APICommand.flags,
...outputListing.flags,
type: flags.string({
description: 'filter results by appType, WEBHOOK_SMART_APP, LAMBDA_SMART_APP, API_ONLY',
multiple: false,
Expand Down Expand Up @@ -67,8 +68,8 @@ export default class AppsList extends ListingOutputAPICommand<App, App> {
primaryKeyName = 'appId'
sortKeyName = 'displayName'

protected tableFieldDefinitions = tableFieldDefinitions
protected listTableFieldDefinitions = ['displayName', 'appType', 'appId']
tableFieldDefinitions = tableFieldDefinitions
listTableFieldDefinitions = ['displayName', 'appType', 'appId']

async run(): Promise<void> {
const { args, argv, flags } = this.parse(AppsList)
Expand Down Expand Up @@ -117,6 +118,6 @@ export default class AppsList extends ListingOutputAPICommand<App, App> {
return this.client.apps.list(appListOptions)
}

await this.processNormally(args.id, listApps, id => this.client.apps.get(id))
await outputListing(this, args.id, listApps, id => this.client.apps.get(id))
}
}
83 changes: 35 additions & 48 deletions packages/cli/src/commands/config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import fs from 'fs'
import yaml from 'js-yaml'
import { flags } from '@oclif/command'

import { cliConfig, IOFormat, ListingOutputAPICommand, TableFieldDefinition } from '@smartthings/cli-lib'
import { buildOutputFormatter, calculateOutputFormat, cliConfig, IOFormat, outputItem, outputList, outputListing,
SmartThingsCommand, stringTranslateToId, TableFieldDefinition, writeOutput } from '@smartthings/cli-lib'


function reservedKey(key: string): boolean {
Expand All @@ -24,21 +24,18 @@ export class ConfigItem {
constructor(key: string, data: ConfigData, profileName: string) {
this.name = key
this.active = reservedKey(key) ? 'N/A' : key === profileName ? 'true' : ''
this.token = data.token || ''
this.apiUrl = data.clientIdProvider?.baseURL || ''
this.token = data?.token ?? ''
this.apiUrl = data?.clientIdProvider?.baseURL ?? ''
this.data = data
}

}

// TODO: make non-API commands listable as well so we don't have to extend
// APICommand here (or anywhere else we need to do non-API commands that list
// things)
export default class ConfigCommand extends ListingOutputAPICommand<ConfigItem, ConfigItem> {
export default class ConfigCommand extends SmartThingsCommand {
static description = 'list config file entries'

static flags = {
...ListingOutputAPICommand.flags,
...SmartThingsCommand.flags,
...outputListing.flags,
verbose: flags.boolean({
description: 'Include additional data in table output',
char: 'v',
Expand All @@ -53,60 +50,50 @@ export default class ConfigCommand extends ListingOutputAPICommand<ConfigItem, C
primaryKeyName = 'name'
sortKeyName = 'name'

protected listTableFieldDefinitions: TableFieldDefinition<ConfigItem>[] = [
listTableFieldDefinitions: TableFieldDefinition<ConfigItem>[] = [
'name',
{ label: 'Active', value: (item) => reservedKey(item.name) ? 'N/A' : item.active ? 'true' : '' },
]

protected tableFieldDefinitions: TableFieldDefinition<ConfigItem>[] = [
tableFieldDefinitions: TableFieldDefinition<ConfigItem>[] = [
...this.listTableFieldDefinitions,
{ label: 'Definition', value: (item) => yaml.safeDump(item.data) },
]

protected buildListTableOutput(sortedList: ConfigItem[]): string {
async run(): Promise<void> {
const { args, argv, flags } = this.parse(ConfigCommand)
await super.setup(args, argv, flags)

if (this.flags.verbose) {
this.listTableFieldDefinitions.push('token')
if (this.flags.verbose && !!sortedList.find(it => it.data.clientIdProvider?.baseURL)) {
}

const getConfig = async (name: string): Promise<ConfigItem> => {
const config = cliConfig.getRawConfigData()
return new ConfigItem(name, config[name], this.profileName)
}
const listConfigs = async (): Promise<ConfigItem[]> => {
const config = cliConfig.getRawConfigData()
const list = Object.keys(config).map(it => {
return new ConfigItem(it, config[it], this.profileName)
})
if (this.flags.verbose && !!list.find(it => it.data?.clientIdProvider?.baseURL)) {
this.listTableFieldDefinitions.push('apiUrl')
}
return list
}

return super.buildListTableOutput(sortedList)
}

async run(): Promise<void> {
const { args, argv, flags } = this.parse(ConfigCommand)
await super.setup(args, argv, flags)

const outputOptions = this.outputOptions
if (!args.name && outputOptions.format === IOFormat.JSON || outputOptions.format === IOFormat.YAML) {
const data = cliConfig.getRawConfigData()
const output = outputOptions.format === IOFormat.JSON ?
JSON.stringify(data, null, outputOptions.indentLevel) :
yaml.safeDump(data, { indent: outputOptions.indentLevel })

if (this.outputOptions.filename) {
fs.writeFileSync(this.outputOptions.filename, output)
if (args.name) {
const id = await stringTranslateToId(this, args.name, listConfigs)
await outputItem(this, () => getConfig(id))
} else {
const outputFormat = calculateOutputFormat(this)
if (outputFormat === IOFormat.COMMON) {
await outputList(this, listConfigs, true)
} else {
process.stdout.write(output)
if (!output.endsWith('\n')) {
process.stdout.write('\n')
}
const outputFormatter = buildOutputFormatter(this)
await writeOutput(outputFormatter(cliConfig.getRawConfigData()), this.flags.output)
}
} else {
await this.processNormally(
args.name,
async () => {
const config = cliConfig.getRawConfigData()
return Object.keys(config).map(it => {
return new ConfigItem(it, config[it], this.profileName)
})
},
async (name) => {
const config = cliConfig.getRawConfigData()
return new ConfigItem(name, config[name], this.profileName)
},
)
}
}
}
15 changes: 7 additions & 8 deletions packages/cli/src/commands/deviceprofiles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DeviceProfile } from '@smartthings/core-sdk'

import {APICommand, ListingOutputAPICommand, TableFieldDefinition} from '@smartthings/cli-lib'
import {APICommand, outputListing, TableFieldDefinition} from '@smartthings/cli-lib'

import { flags } from '@oclif/command'

Expand All @@ -20,11 +20,12 @@ export function buildTableOutput(this: APICommand, data: DeviceProfile): string
return table.toString()
}

export default class DeviceProfilesList extends ListingOutputAPICommand<DeviceProfile, DeviceProfile> {
export default class DeviceProfilesList extends APICommand {
static description = 'list all device profiles available in a user account or retrieve a single profile'

static flags = {
...ListingOutputAPICommand.flags,
...APICommand.flags,
...outputListing.flags,
verbose: flags.boolean({
description: 'include presentationId and manufacturerName in list output',
char: 'v',
Expand All @@ -50,10 +51,9 @@ export default class DeviceProfilesList extends ListingOutputAPICommand<DevicePr
primaryKeyName = 'id'
sortKeyName = 'name'

listTableFieldDefinitions: TableFieldDefinition<DeviceProfile>[] = ['name', 'status', 'id']

protected listTableFieldDefinitions: TableFieldDefinition<DeviceProfile>[] = ['name', 'status', 'id']

protected buildTableOutput = buildTableOutput
buildTableOutput = buildTableOutput

async run(): Promise<void> {
const { args, argv, flags } = this.parse(DeviceProfilesList)
Expand All @@ -64,8 +64,7 @@ export default class DeviceProfilesList extends ListingOutputAPICommand<DevicePr
this.listTableFieldDefinitions.push({ label: 'Manufacturer Name', value: (item) => item.metadata ? item.metadata.mnmn : '' })
}

await this.processNormally(
args.id,
await outputListing(this, args.id,
() => { return this.client.deviceProfiles.list() },
(id) => { return this.client.deviceProfiles.get(id) },
)
Expand Down
15 changes: 8 additions & 7 deletions packages/cli/src/commands/devices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { flags } from '@oclif/command'

import { Device, DeviceListOptions } from '@smartthings/core-sdk'

import { APICommand, ListingOutputAPICommand, withLocationsAndRooms } from '@smartthings/cli-lib'
import { APICommand, outputListing, withLocationsAndRooms } from '@smartthings/cli-lib'


export type DeviceWithLocation = Device & { location?: string }
Expand All @@ -27,11 +27,12 @@ export function buildTableOutput(this: APICommand, data: Device & { profileId?:
return table.toString()
}

export default class DevicesCommand extends ListingOutputAPICommand<Device, DeviceWithLocation> {
export default class DevicesCommand extends APICommand {
static description = 'list all devices available in a user account or retrieve a single device'

static flags = {
...ListingOutputAPICommand.flags,
...APICommand.flags,
...outputListing.flags,
'location-id': flags.string({
char: 'l',
description: 'filter results by location',
Expand Down Expand Up @@ -70,9 +71,9 @@ export default class DevicesCommand extends ListingOutputAPICommand<Device, Devi

primaryKeyName = 'deviceId'
sortKeyName = 'label'
protected listTableFieldDefinitions = ['label', 'name', 'type', 'deviceId']
listTableFieldDefinitions = ['label', 'name', 'type', 'deviceId']

protected buildTableOutput = buildTableOutput
buildTableOutput = buildTableOutput

async run(): Promise<void> {
const { args, argv, flags } = this.parse(DevicesCommand)
Expand All @@ -90,7 +91,7 @@ export default class DevicesCommand extends ListingOutputAPICommand<Device, Devi
installedAppId: flags['installed-app-id'],
}

await this.processNormally(
await outputListing(this,
args.id,
async () => {
const devices = await this.client.devices.list(deviceListOptions)
Expand All @@ -99,7 +100,7 @@ export default class DevicesCommand extends ListingOutputAPICommand<Device, Devi
}
return devices
},
(id) => {return this.client.devices.get(id) },
id => this.client.devices.get(id),
)
}
}
15 changes: 8 additions & 7 deletions packages/cli/src/commands/locations/rooms.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { flags } from '@oclif/command'
import { LocationItem, Room } from '@smartthings/core-sdk'

import { APICommand, ListingOutputAPICommand } from '@smartthings/cli-lib'
import { APICommand, outputListing } from '@smartthings/cli-lib'


export const tableFieldDefinitions = ['name', 'locationId', 'roomId']
Expand Down Expand Up @@ -32,15 +32,16 @@ export type RoomWithLocation = Room & {
locationName?: string
}

export default class RoomsCommand extends ListingOutputAPICommand<Room, RoomWithLocation> {
export default class RoomsCommand extends APICommand {
static description = 'get a specific room'

static flags = {
...ListingOutputAPICommand.flags,
...APICommand.flags,
locationId: flags.string({
char: 'l',
description: 'a specific locationId to query',
}),
...outputListing.flags,
}

static args = [{
Expand All @@ -55,18 +56,18 @@ export default class RoomsCommand extends ListingOutputAPICommand<Room, RoomWith

protected getRoomsByLocation = getRoomsByLocation

protected listTableFieldDefinitions = tableFieldDefinitions
protected tableFieldDefinitions = tableFieldDefinitions
listTableFieldDefinitions = tableFieldDefinitions
tableFieldDefinitions = tableFieldDefinitions

async run(): Promise<void> {
const { args, argv, flags } = this.parse(RoomsCommand)
await super.setup(args, argv, flags)

const roomsPromise = this.getRoomsByLocation(flags.locationId)
await this.processNormally(
await outputListing(this,
args.idOrIndex,
() => roomsPromise,
async (id) => {
async id => {
const room = (await roomsPromise).find(room => room.roomId === id)
if (!room) {
throw Error(`could not find room with id ${id}`)
Expand Down

0 comments on commit bfa67b6

Please sign in to comment.