import {z} from 'zod' export type GetApiCapabilitiesCapabilityIdCapabilityVersionPresentationArgs = {'Accept-Language'?: string | undefined}; export type GetApiCapabilitiesCapabilityIdCapabilityVersionPresentationOptions = {baseUrl?: string | undefined, Bearer?: string | undefined, fetch?: typeof fetch | undefined}; export const version = z.number().int(); export const formattedLabel = z.string(); export const iconUrl = z.string(); export const alternativeItem = z.object({key: z.string(), value: z.string(), type: z.enum(["inactive", "active"]).optional(), iconUrl: iconUrl.optional(), description: z.string().optional()}); export const alternatives = z.array(alternativeItem); export const stateItem = z.object({label: formattedLabel, alternatives: alternatives.optional()}); export const argumentType = z.string(); export const pushButton = z.object({command: z.string(), argument: z.string().optional(), argumentType: argumentType.optional()}); export const value = z.string(); export const valueType = z.string(); export const toggleSwitchForDashboard = z.object({command: z.object({name: z.string().optional(), on: z.string(), off: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value.optional(), on: z.string(), off: z.string(), valueType: valueType.optional(), alternatives: alternatives.optional()}).optional()}); export const switchForDashboard = z.object({command: z.object({name: z.string().optional(), on: z.string(), off: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value.optional(), on: z.string(), off: z.string(), valueType: valueType.optional(), alternatives: alternatives.optional()}).optional()}); export const standbyPowerSwitchForDashboard = z.object({command: z.object({name: z.string().optional(), on: z.string(), off: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value, valueType: valueType.optional(), on: z.string(), off: z.string(), label: formattedLabel.optional(), alternatives: alternatives.optional()}).optional()}); export const statelessPowerToggleForDashboard = z.object({command: z.string(), argument: z.string().optional(), argumentType: argumentType.optional()}); export const playPause = z.object({command: z.object({name: z.string().optional(), play: z.string(), pause: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value, valueType: valueType.optional(), play: z.string(), pause: z.string(), alternatives: alternatives.optional()})}); export const playStop = z.object({command: z.object({name: z.string().optional(), play: z.string(), stop: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value, play: z.string(), stop: z.string(), alternatives: alternatives.optional(), valueType: valueType.optional()})}); export const group = z.string(); export const actionItem = z.object({displayType: z.enum(["pushButton", "toggleSwitch", "switch", "standbyPowerSwitch", "statelessPowerToggle", "playPause", "playStop"]), pushButton: pushButton.optional(), toggleSwitch: toggleSwitchForDashboard.optional(), switch: switchForDashboard.optional(), standbyPowerSwitch: standbyPowerSwitchForDashboard.optional(), statelessPowerToggle: statelessPowerToggleForDashboard.optional(), playPause: playPause.optional(), playStop: playStop.optional(), group: group.optional()}); export const step = z.number(); export const range = z.array(z.number()); export const supportedValuesForNumericConstraints = z.string(); export const unit = z.string(); export const stepperWithAvailableSize = z.object({command: z.object({name: z.string().optional(), increase: z.string().optional(), decrease: z.string().optional(), argumentType: argumentType.optional()}), step: step, range: range, supportedValues: supportedValuesForNumericConstraints.optional(), state: z.object({value: value, unit: unit.optional(), valueType: valueType.optional(), label: z.string().optional(), alternatives: alternatives.optional()}), availableSizes: z.array(z.enum(["2x1", "3x1", "4x1", "1x2", "2x2"])).optional()}); export const supportedValues = z.string(); export const listWithAvailableSize = z.object({command: z.object({name: z.string().optional(), description: z.string().optional(), alternatives: alternatives, argumentType: argumentType.optional(), supportedValues: supportedValues.optional()}), state: z.object({value: value, valueType: valueType.optional(), alternatives: alternatives}).optional(), availableSizes: z.array(z.enum(["2x1", "3x1", "4x1", "1/3x1", "2x2"])).optional()}); export const pushButtonWithAvailableSize = z.object({command: z.string(), argument: z.string().optional(), argumentType: argumentType.optional(), iconUrl: z.string().optional(), availableSizes: z.array(z.enum(["1x1", "2x1", "3x1", "4x1", "1/3x1", "2x2"])).optional()}); export const argumentName = z.string(); export const listForInvokeButtonArgument = z.object({alternatives: alternatives, supportedValues: supportedValues.optional(), label: z.string()}); export const stateInvokeButtonArgument = z.object({label: z.string(), alternatives: alternatives.optional()}); export const argumentsForInvokeButton = z.object({name: argumentName, value: z.string(), argumentType: argumentType.optional(), displayType: z.enum(["list", "state"]).optional(), list: listForInvokeButtonArgument.optional(), state: stateInvokeButtonArgument.optional()}); export const commandsForInvokeButton = z.object({state: z.string(), label: z.string().optional(), iconUrl: z.string().optional(), command: z.object({name: z.string(), argument: z.string().optional(), argumentType: argumentType.optional(), confirmation: z.object({label: z.string(), title: z.string().optional(), description: z.string().optional()}).optional(), arguments: z.array(argumentsForInvokeButton).optional(), supportedValues: z.string().optional()})}); export const invokeButtonWithAvailableSize = z.object({value: z.string(), valueType: valueType.optional(), refreshInterval: z.number().int().optional(), commands: z.array(commandsForInvokeButton), availableSizes: z.array(z.enum(["1x1", "2x1", "3x1", "4x1", "1/3x1", "2x2"])).optional()}); export const stateWithAvailableSize = z.object({label: formattedLabel, unit: unit.optional(), alternatives: alternatives.optional(), availableSizes: z.array(z.literal("2x1")).optional()}); export const sliderWithAvailableSize = z.object({range: range, step: step.optional(), unit: unit.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), alternatives: alternatives.optional(), command: z.string(), argumentType: argumentType.optional(), value: value.optional(), valueType: valueType.optional(), availableSizes: z.array(z.enum(["4x1", "4x2"])).optional()}); export const emptyWithAvailableSize = z.object({availableSizes: z.array(z.enum(["1x1", "2x1", "3x1", "4x1", "1/3x1", "1x2", "2x2"])).optional()}); export const panelItemForCapability = z.object({label: z.string().optional(), displayType: z.enum(["stepper", "list", "pushButton", "invokeButton", "state", "slider", "empty"]), stepper: stepperWithAvailableSize.optional(), list: listWithAvailableSize.optional(), pushButton: pushButtonWithAvailableSize.optional(), invokeButton: invokeButtonWithAvailableSize.optional(), state: stateWithAvailableSize.optional(), slider: sliderWithAvailableSize.optional(), empty: emptyWithAvailableSize.optional()}); export const dashboardForCapability = z.object({states: z.array(stateItem).optional(), actions: z.array(actionItem).optional(), panelItems: z.array(panelItemForCapability).optional()}); export const toggleSwitch = z.object({command: z.object({name: z.string().optional(), on: z.string(), off: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value, valueType: valueType.optional(), on: z.string(), off: z.string(), label: formattedLabel.optional(), alternatives: alternatives.optional()}).optional()}); export const standbyPowerSwitch = z.object({command: z.object({name: z.string().optional(), on: z.string(), off: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value, valueType: valueType.optional(), on: z.string(), off: z.string(), label: formattedLabel.optional(), alternatives: alternatives.optional()}).optional()}); export const switch = z.object({command: z.object({name: z.string().optional(), on: z.string(), off: z.string(), argumentType: argumentType.optional()}), state: z.object({value: value, valueType: valueType.optional(), on: z.string(), off: z.string(), label: formattedLabel.optional(), alternatives: alternatives.optional()}).optional()}); export const sliderType = z.object({range: range, step: step.optional(), unit: unit.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), alternatives: alternatives.optional(), command: z.string().optional(), argumentType: argumentType.optional(), value: value.optional(), valueType: valueType.optional()}); export const textButton = z.object({command: z.string().optional(), value: value.optional(), buttons: z.array(z.object({key: z.string(), label: z.string(), state: z.string().optional()})), supportedValues: supportedValues.optional()}); export const listForDetailView = z.object({command: z.object({name: z.string().optional(), description: z.string().optional(), alternatives: alternatives, argumentType: argumentType.optional(), supportedValues: supportedValues.optional()}), state: z.object({value: value, valueType: valueType.optional(), alternatives: alternatives}).optional()}); export const textField = z.object({command: z.string(), argumentType: argumentType.optional(), value: value.optional(), valueType: valueType.optional(), range: range.optional()}); export const numberField = z.object({value: value.optional(), valueType: valueType.optional(), unit: unit.optional(), command: z.string(), argumentType: argumentType.optional(), range: range.optional(), supportedValues: supportedValuesForNumericConstraints.optional()}); export const stepper = z.object({command: z.object({name: z.string().optional(), increase: z.string().optional(), decrease: z.string().optional(), argumentType: argumentType.optional()}), step: step, range: range, supportedValues: supportedValuesForNumericConstraints.optional(), value: value.optional(), valueType: valueType.optional()}); export const state = z.object({label: formattedLabel, unit: unit.optional(), alternatives: alternatives.optional()}); export const operator = z.enum(["CONTAINS", "DOES_NOT_CONTAIN", "EQUALS", "DOES_NOT_EQUAL", "GREATER_THAN", "GREATER_THAN_OR_EQUALS", "LESS_THAN", "LESS_THAN_OR_EQUALS", "ONE_OF"]); export const visibleConditionBase = z.object({value: value, valueType: valueType.optional(), operator: operator, operand: z.string()}); export const detailViewForCapability = z.array(z.object({label: z.string(), displayType: z.enum(["toggleSwitch", "standbyPowerSwitch", "switch", "slider", "pushButton", "textButton", "playPause", "playStop", "list", "textField", "numberField", "stepper", "state"]), toggleSwitch: toggleSwitch.optional(), standbyPowerSwitch: standbyPowerSwitch.optional(), switch: switch.optional(), slider: sliderType.optional(), pushButton: pushButton.optional(), textButton: textButton.optional(), playPause: playPause.optional(), playStop: playStop.optional(), list: listForDetailView.optional(), textField: textField.optional(), numberField: numberField.optional(), stepper: stepper.optional(), state: state.optional(), visibleCondition: visibleConditionBase.optional()})); export const descriptionForAutomationItem = z.string(); export const descriptionForAutomatioDisplayType = z.string(); export const sliderForAutomationCondition = z.object({range: range, step: step.optional(), unit: unit.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), alternatives: alternatives.optional(), value: value, valueType: valueType.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const listForAutomationCondition = z.object({alternatives: alternatives, supportedValues: supportedValues.optional(), value: value, valueType: valueType.optional(), description: descriptionForAutomatioDisplayType.optional(), multiSelectable: z.boolean().optional()}); export const supportedValuesForDynamicList = z.object({value: z.string(), valueMap: z.object({key: z.string(), value: z.string()}).optional()}); export const alternativesForDynamicList = z.array(alternativeItem); export const dynamicListForAutomationCondition = z.object({value: value, valueType: z.string().optional(), supportedValues: supportedValuesForDynamicList, alternatives: alternativesForDynamicList.optional(), description: descriptionForAutomatioDisplayType.optional(), multiSelectable: z.boolean().optional()}); export const numberFieldForAutomationCondition = z.object({value: value, valueType: valueType.optional(), unit: unit.optional(), range: range.optional(), alternatives: alternatives.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const textFieldForAutomationCondition = z.object({value: value, valueType: valueType.optional(), range: range.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const enumSliderForAutomationCondition = z.object({alternatives: alternatives, value: value, supportedOperators: z.array(z.object({operator: z.enum(["EQUALS", "GREATER_THAN_OR_EQUALS", "LESS_THAN_OR_EQUALS"]), label: z.string()})).optional()}); export const unitWithoutPatternForPresentation = z.string(); export const numberPickerForAutomationCondition = z.object({value: value, valueType: valueType.optional(), unit: unitWithoutPatternForPresentation.optional(), range: range.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const sliderForAutomationAction = z.object({range: range, step: step.optional(), unit: unit.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), alternatives: alternatives.optional(), command: z.string(), argumentType: argumentType.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const listForAutomationAction = z.object({alternatives: alternatives, supportedValues: supportedValues.optional(), command: z.string().optional(), argumentType: argumentType.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const dynamicListForAutomationAction = z.object({command: z.string().optional(), argumentType: z.string().optional(), supportedValues: supportedValuesForDynamicList, alternatives: alternativesForDynamicList.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const textFieldForAutomationAction = z.object({command: z.string(), argumentType: argumentType.optional(), range: range.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const numberFieldForAutomationAction = z.object({command: z.string(), argumentType: argumentType.optional(), unit: unit.optional(), range: range.optional(), alternatives: alternatives.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const numberPickerForAutomationAction = z.object({command: z.string(), argumentType: argumentType.optional(), unit: unitWithoutPatternForPresentation.optional(), range: range.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), description: descriptionForAutomatioDisplayType.optional()}); export const sliderForArgument = z.object({range: range, step: step.optional(), unit: unit.optional(), supportedValues: supportedValuesForNumericConstraints.optional(), name: argumentName, argumentType: argumentType.optional(), alternatives: alternatives.optional()}); export const listForArgument = z.object({alternatives: alternatives, supportedValues: supportedValues.optional(), name: argumentName, argumentType: argumentType.optional()}); export const textFieldForArgument = z.object({name: argumentName, argumentType: argumentType.optional(), range: range.optional()}); export const numberFieldForArgument = z.object({name: argumentName, unit: unit.optional(), argumentType: argumentType.optional(), range: range.optional(), supportedValues: supportedValuesForNumericConstraints.optional()}); export const multiArgCommand = z.object({command: z.string(), arguments: z.array(z.object({label: z.string(), displayType: z.enum(["slider", "list", "textField", "numberField"]), slider: sliderForArgument.optional(), list: listForArgument.optional(), textField: textFieldForArgument.optional(), numberField: numberFieldForArgument.optional()})), supportedValues: z.string().optional()}); export const automationForCapability = z.object({conditions: z.array(z.object({label: z.string(), description: descriptionForAutomationItem.optional(), displayType: z.enum(["slider", "list", "dynamicList", "numberField", "textField", "enumSlider", "numberPicker"]), slider: sliderForAutomationCondition.optional(), list: listForAutomationCondition.optional(), dynamicList: dynamicListForAutomationCondition.optional(), numberField: numberFieldForAutomationCondition.optional(), textField: textFieldForAutomationCondition.optional(), enumSlider: enumSliderForAutomationCondition.optional(), numberPicker: numberPickerForAutomationCondition.optional(), emphasis: z.boolean().optional(), visibleCondition: visibleConditionBase.optional()})).optional(), actions: z.array(z.object({label: z.string(), description: descriptionForAutomationItem.optional(), displayType: z.enum(["slider", "list", "dynamicList", "numberField", "textField", "numberPicker", "multiArgCommand"]), slider: sliderForAutomationAction.optional(), list: listForAutomationAction.optional(), dynamicList: dynamicListForAutomationAction.optional(), textField: textFieldForAutomationAction.optional(), numberField: numberFieldForAutomationAction.optional(), numberPicker: numberPickerForAutomationAction.optional(), multiArgCommand: multiArgCommand.optional(), emphasis: z.boolean().optional(), visibleCondition: visibleConditionBase.optional()})).optional()}); export const presentationSettings = z.object({temperatureConversions: z.array(z.object({value: value, unit: unit.optional()})).optional()}); export const capabilityPresentation = z.object({id: z.string(), version: version, dashboard: dashboardForCapability.optional(), detailView: detailViewForCapability.optional(), automation: automationForCapability.optional(), presentationSettings: presentationSettings.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get a Capability Presentation by ID and Version * * GET /capabilities/{capabilityId}/{capabilityVersion}/presentation */ export const getApiCapabilitiesCapabilityIdCapabilityVersionPresentation = async (args: GetApiCapabilitiesCapabilityIdCapabilityVersionPresentationArgs, options?: GetApiCapabilitiesCapabilityIdCapabilityVersionPresentationOptions) => { const {baseUrl = "https://api.smartthings.com/v1", fetch: fetchFn = fetch, Bearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args['Accept-Language'] != null) headers.set("Accept-Language", String(args['Accept-Language'])) if (Bearer !== undefined) headers.set('authorization', `Bearer ${Bearer}`) const url = `${baseUrl.replace(/\/+$/, '')}/capabilities/${encodeURIComponent(String(args.capabilityId))}/${encodeURIComponent(String(args.capabilityVersion))}/presentation${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(capabilityPresentation, await res.json()) };