forked from SmartThingsCommunity/smartthings-cli
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathapi-command.ts
More file actions
120 lines (101 loc) · 4.06 KB
/
api-command.ts
File metadata and controls
120 lines (101 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import log4js from 'log4js'
import { osLocale } from 'os-locale'
import { Argv } from 'yargs'
import { Authenticator, HttpClientHeaders, SmartThingsClient, WarningFromHeader } from '@smartthings/core-sdk'
import { coreSDKLoggerFromLog4JSLogger } from '../log-utils.js'
import { ClientIdProvider, defaultClientIdProvider, loginAuthenticator } from '../login-authenticator.js'
import { SmartThingsCommand, SmartThingsCommandFlags, smartThingsCommand, smartThingsCommandBuilder } from './smartthings-command.js'
import { newBearerTokenAuthenticator, newSmartThingsClient } from './util/st-client-wrapper.js'
export const userAgent = '@smartthings/cli'
// TODO: BEGIN remove
// In the second phase of this work, we will remove these helper functions in favor of those
// in help.ts.
const toURL = (nameOrURL: string): string => nameOrURL.startsWith('http')
? nameOrURL
: `https://developer.smartthings.com/docs/api/public/#operation/${nameOrURL}`
export const apiDocsURL = (...names: string[]): string => 'For API information, see:\n ' +
names.map(name => toURL(name)).join('\n ')
// TODO: END REMOVE
export type APICommandFlags = SmartThingsCommandFlags & {
token?: string
language?: string
}
export const apiCommandBuilder = <T extends object>(yargs: Argv<T>): Argv<T & APICommandFlags> =>
smartThingsCommandBuilder(yargs)
.option('token', {
alias: 't',
desc: 'the auth token to use',
type: 'string',
default: process.env.SMARTTHINGS_TOKEN,
hidden: true,
})
.option('language', {
desc: 'ISO language code or "NONE" to not specify a language. Defaults to the OS locale',
type: 'string',
})
export type APICommand<T extends APICommandFlags = APICommandFlags> = SmartThingsCommand<T> & {
token?: string
clientIdProvider: ClientIdProvider
authenticator: Authenticator
client: SmartThingsClient
}
/**
* Base for commands that need to use Rest API via the SmartThings Core SDK.
*/
export const apiCommand = async <T extends APICommandFlags>(
flags: T,
addAdditionalHeaders?: (stCommand: SmartThingsCommand<T>, headers: HttpClientHeaders) => void,
): Promise<APICommand<T>> => {
const stCommand = await smartThingsCommand(flags)
// The `|| undefined` at then end of this line is to normalize falsy values to `undefined`.
const token = (flags.token ?? stCommand.cliConfig.stringConfigValue('token')) || undefined
const calculateClientIdProvider = (): ClientIdProvider => {
const configClientIdProvider = stCommand.profile.clientIdProvider
if (configClientIdProvider) {
if (typeof configClientIdProvider !== 'object') {
stCommand.logger.error('ignoring invalid configClientIdProvider')
} else {
// TODO: do more type checking here eventually
return configClientIdProvider as ClientIdProvider
}
}
return defaultClientIdProvider
}
const clientIdProvider = calculateClientIdProvider()
const logger = coreSDKLoggerFromLog4JSLogger(log4js.getLogger('rest-client'))
const buildHeaders = async (): Promise<HttpClientHeaders> => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const headers: HttpClientHeaders = { 'User-Agent': userAgent }
if (flags.language) {
if (flags.language !== 'NONE') {
headers['Accept-Language'] = flags.language
}
} else {
headers['Accept-Language'] = await osLocale()
}
return headers
}
const headers = await buildHeaders()
if (addAdditionalHeaders) {
addAdditionalHeaders(stCommand, headers)
}
const authenticator = token
? newBearerTokenAuthenticator(token)
: loginAuthenticator(`${stCommand.dataDir}/credentials.json`, stCommand.profileName, clientIdProvider, userAgent)
const warningLogger = (warnings: WarningFromHeader[] | string): void => {
const message = 'Warnings from API:\n' + (typeof(warnings) === 'string'
? warnings
: stCommand.tableGenerator.buildTableFromList(warnings, ['code', 'agent', 'text', 'date']))
logger.warn(message)
console.warn(message)
}
const client = newSmartThingsClient(authenticator,
{ urlProvider: clientIdProvider, logger, headers, warningLogger })
return {
...stCommand,
token,
clientIdProvider,
authenticator,
client,
}
}