{"version":3,"file":"index.cjs","sources":["../../../scripts/sync-user-types/connection.ts","../../../scripts/sync-user-types/constants.ts","../../../scripts/sync-user-types/action-generator.ts","../../../scripts/sync-user-types/entity-generator.ts","../../../scripts/sync-user-types/index.ts"],"sourcesContent":["import { createConnection, createLongLivedTokenAuth, Auth, getServices, getStates, HassEntity, HassServices } from 'home-assistant-js-websocket';\nimport WebSocket from 'ws';\n\ninterface HaWebSocket extends WebSocket {\n  haVersion: string;\n}\n\nconst MSG_TYPE_AUTH_REQUIRED = \"auth_required\";\nconst MSG_TYPE_AUTH_INVALID = \"auth_invalid\";\nconst MSG_TYPE_AUTH_OK = \"auth_ok\";\nconst ERR_CANNOT_CONNECT = 1;\nconst ERR_INVALID_AUTH = 2;\n\nexport function createSocket(\n  auth: Auth,\n): Promise<HaWebSocket> {\n  // Convert from http:// -> ws://, https:// -> wss://\n  const url = auth.wsUrl;\n\n  console.info(\n    \"[Auth phase] Initializing WebSocket connection to Home Assistant\",\n    url,\n  );\n\n  function connect(\n    triesLeft: number,\n    promResolve: (socket: HaWebSocket) => void,\n    promReject: (err: number) => void,\n  ) {\n    console.info(\n      `[Auth Phase] Connecting to Home Assistant... Tries left: ${triesLeft}`,\n      url,\n    );\n\n    const socket = new WebSocket(url, {\n      rejectUnauthorized: false,\n    }) as HaWebSocket;\n\n    // If invalid auth, we will not try to reconnect.\n    let invalidAuth = false;\n\n    const closeMessage = (ev: {\n      wasClean: boolean;\n      code: number;\n      reason: string;\n      target: WebSocket;\n    }) => {\n      let errorMessage;\n      if (ev && ev.code && ev.code !== 1000) {\n        errorMessage = `WebSocket connection to Home Assistant closed with code ${ev.code} and reason ${ev.reason}`;\n      }\n      closeOrError(errorMessage);\n    };\n\n    const errorMessage = (ev: {\n      message: string;\n      type: string;\n      target: WebSocket;\n    }) => {\n      // If we are in error handler make sure close handler doesn't also fire.\n      socket.removeEventListener(\"close\", closeMessage);\n      let errMessage =\n        \"Disconnected from Home Assistant with a WebSocket error\";\n      if (ev.message) {\n        errMessage += ` with message: ${ev.message}`;\n      }\n      closeOrError(errMessage);\n    };\n\n    const closeOrError = (errorText?: string) => {\n      if (errorText) {\n        console.info(\n          `WebSocket Connection to Home Assistant closed with an error: ${errorText}`,\n        );\n      }\n      if (invalidAuth) {\n        promReject(ERR_INVALID_AUTH);\n        return;\n      }\n\n      // Reject if we no longer have to retry\n      if (triesLeft === 0) {\n        // We never were connected and will not retry\n        promReject(ERR_CANNOT_CONNECT);\n        return;\n      }\n\n      const newTries = triesLeft === -1 ? -1 : triesLeft - 1;\n      // Try again in a second\n      setTimeout(() => connect(newTries, promResolve, promReject), 1000);\n    };\n\n    // Auth is mandatory, so we can send the auth message right away.\n    const handleOpen = async (): Promise<void> => {\n      try {\n        if (auth.expired) {\n          await auth.refreshAccessToken();\n        }\n        socket.send(\n          JSON.stringify({\n            type: \"auth\",\n            access_token: auth.accessToken,\n          }),\n        );\n      } catch (err) {\n        // Refresh token failed\n        invalidAuth = err === ERR_INVALID_AUTH;\n        socket.close();\n      }\n    };\n\n    const handleMessage = (event: WebSocket.MessageEvent) => {\n      const message = JSON.parse(event.data as string);\n\n      console.info(\n        `[Auth phase] Received a message of type ${message.type}`,\n        message,\n      );\n\n      switch (message.type) {\n        case MSG_TYPE_AUTH_INVALID:\n          invalidAuth = true;\n          socket.close();\n          break;\n\n        case MSG_TYPE_AUTH_OK:\n          socket.removeEventListener(\"open\", handleOpen);\n          socket.removeEventListener(\"message\", handleMessage);\n          socket.removeEventListener(\"close\", closeMessage);\n          socket.removeEventListener(\"error\", errorMessage);\n          socket.haVersion = message.ha_version;\n          promResolve(socket);\n          break;\n\n        default:\n          // We already send this message when socket opens\n          if (message.type !== MSG_TYPE_AUTH_REQUIRED) {\n            console.info(\"[Auth phase] Unhandled message\", message);\n          }\n      }\n    };\n\n    socket.addEventListener(\"open\", handleOpen);\n    socket.addEventListener(\"message\", handleMessage);\n    socket.addEventListener(\"close\", closeMessage);\n    socket.addEventListener(\"error\", errorMessage);\n  }\n\n  return new Promise((resolve, reject) => connect(3, resolve, reject));\n}\n\n\nexport async function connect(url: string, token: string): Promise<{\n  services: HassServices,\n  states: HassEntity[],\n}> {\n  try {\n    const auth = createLongLivedTokenAuth(url, token);\n    const connection = await createConnection({\n      auth,\n      // @ts-expect-error - no way to fix this without providing an override for the types\n      // as the websocket definition is different\n      createSocket: () => createSocket(auth),\n    });\n    const services = await getServices(connection);\n    const states = await getStates(connection);\n    connection.close();\n    return {\n      services,\n      states,\n    }\n  } catch (err) {\n    console.error('err', err);\n    throw new Error('Failed to connect to Home Assistant');\n  }\n}\n","\n\nexport const DEFAULT_FILENAME = 'supported-types.d.ts';\n\nexport const REMAPPED_TYPES: Record<string, string> = {\n  hs_color: `[number, number]`,\n  rgb_color: `[number, number, number]`,\n  rgbw_color: `[number, number, number, number]`,\n  rgbww_color: `[number, number, number, number, number]`,\n  group_members: `string[]`,\n  media_content_id: `string | number`,\n  color_temp_kelvin: `number`,\n  white: 'boolean',\n  color_temp: `number`,\n  xy_color: `[number, number]`,\n};\n","import { HassService, HassServices } from 'home-assistant-js-websocket';\nimport _ from 'lodash';\nimport { REMAPPED_TYPES } from './constants';\n\ntype SelectorValues = string | number | boolean | null;\ntype SelectorOption = {\n  [key: string]: SelectorValues;\n}\n\ntype Selector = {\n  \n  select?: {\n    [key: string]: object | {\n      value: string;\n    }[] | string[];\n  }\n  number?: SelectorOption;\n  object?: SelectorOption;\n  text?: SelectorOption;\n  entity?: SelectorOption;\n  boolean?: SelectorOption;\n  datetime?: SelectorOption;\n  duration?: SelectorOption;\n};\n\nconst resolveSelectorType = (selector: Selector) => {\n  if (!selector) return 'object';\n  // there only ever seems to be one key under the selector object\n  const keys = Object.keys(selector);\n  if (keys.includes('number')) return 'number';\n  if (keys.includes('object')) return 'object';\n  if (keys.includes('duration')) return `{\n    hours?: number;\n    days?: number;\n    minutes?: number;\n    seconds?: number;\n  }`;\n  const stringTypes = [\n    'text',\n    'entity',\n    'datetime',\n    'time',\n    'date',\n    'addon',\n    'backup_location',\n    'icon',\n    'conversation_agent',\n    'device',\n    'theme',\n  ];\n  const isStringType = stringTypes.some(type => keys.includes(type));\n  if (isStringType) return 'string';\n  if (keys.includes('boolean')) return 'boolean';\n  if (keys.includes('select')) {\n    const options = selector?.select?.options;\n    if (!_.isArray(options) || options.length === 0) return 'unknown';\n    return `${options.map(option => `'${typeof option === 'string' ? option : option.value}'`).join(' | ')}`;\n  }\n  // unknown types\n  return 'unknown';\n}\n\nfunction sanitizeString(str: string | boolean | number): string {\n  return `${str}`.replace(/\"/g, \"'\").replace(/[\\n\\r]+/g, ' ');\n}\n\ninterface ActionTypeOptions {\n  domainWhitelist?: string[];\n  domainBlacklist?: string[];\n  serviceWhitelist?: string[];\n  serviceBlacklist?: string[];\n}\n\nexport const generateActionTypes = (input: HassServices, {\n  domainWhitelist = [],\n  domainBlacklist = [],\n  serviceWhitelist = [],\n  serviceBlacklist = [],\n}: ActionTypeOptions) => {\n  const interfaces = Object.entries(input).map(([domain, actions]) => {\n    const camelDomain = _.camelCase(domain);\n    if (domainBlacklist.length > 0 && (domainBlacklist.includes(camelDomain) || domainBlacklist.includes(domain))) return '';\n    if (domainWhitelist.length > 0 && (!domainWhitelist.includes(camelDomain) || !domainWhitelist.includes(domain))) return '';\n    const domainActions = Object.entries(actions).map(([action, { fields, description }]) => {\n      const camelAction = _.camelCase(action);\n      if (serviceBlacklist.length > 0 && (serviceBlacklist.includes(camelAction) || serviceBlacklist.includes(action))) return '';\n      if (serviceWhitelist.length > 0 && (!serviceWhitelist.includes(camelAction) || !serviceWhitelist.includes(action))) return '';\n      function processFields(fields: HassService['fields']): string[] {\n        return Object.entries(fields).map(([field, { selector, example, description, ...rest }]) => {\n          const required = rest.required ?? false;\n          const remapByDomainActionField = `${domain}.${action}.${field}`;\n          const remapByActionField = `${action}.${field}`;\n          const remapByField = field;\n          const domainActionFieldOverride = remapByDomainActionField in REMAPPED_TYPES ? REMAPPED_TYPES[remapByDomainActionField] : undefined;\n          const actionFieldOverride = remapByActionField in REMAPPED_TYPES ? REMAPPED_TYPES[remapByActionField] : undefined;\n          const fieldOverride = remapByField in REMAPPED_TYPES ? REMAPPED_TYPES[remapByField] : undefined;\n          const _selector = selector as Selector;\n          const overrides = domainActionFieldOverride || actionFieldOverride || fieldOverride;\n          // some fields come back as an incorrect type but we know these should be something specific, these are hard coded in the REMAPPED_TYPES constant\n          const type = typeof overrides === 'string' ? overrides : resolveSelectorType(_selector);\n          let constraints = '';\n          if (_.isObject(selector)) {\n            const ignoredKeys = ['select', 'entity', 'theme', 'constant', 'text', 'device'];\n            constraints = Object.entries(_selector || {})\n              .filter(([_key, value]) => _key && _.isObject(value) && !ignoredKeys.includes(_key))\n              .map(([key, value]) => ` ${key}: ${Object.entries(value || {} as object).map(([key, value]) => `${key}: ${value}`).join(', ')}`).join(', ');\n            constraints = constraints ? ` @constraints ${constraints}` : '';\n          }\n          const exampleUsage = example ? ` @example ${example}` : '';\n          const isAdvancedFields = field === 'advanced_fields';\n          const comment = `${description ?? ''}${exampleUsage ?? ''}${constraints}`;\n          return isAdvancedFields && 'fields' in rest ? processFields(rest.fields as HassService['fields']).join('\\n') : `//${comment ? sanitizeString(` ${comment}`) : ''}\\n${field}${required ? '' : '?'}: ${type};`;\n        });\n      }     \n      // the data passed to the ServiceFunction<object>\n      const data = processFields(fields);\n      // the data passed to the ServiceFunction<object>\n      const actionData = `${Object.keys(fields).length === 0 ? 'object' : `{${data.join('\\n')}}`}`;\n      return `// ${sanitizeString(description)}\n        ${camelAction}: ServiceFunction<object, T, ${actionData}>;\n      `;\n    }).join('')\n    const result = `${camelDomain}: {\n        ${domainActions}\n      }\n    `;\n    return result;\n  });\n  return interfaces.join('');\n}","import { HassEntity } from 'home-assistant-js-websocket';\n\nexport const generateEntityType = (input: HassEntity[]) => {\n  return input.map(e => `'${e.entity_id}'`).join(' | ');\n}\n","// purposely adding js extensions here so the extensions stay in the output.\nimport { connect } from './connection.js';\nimport { generateActionTypes } from './action-generator.js';\nimport { generateEntityType } from './entity-generator.js';\nimport { writeFileSync } from 'fs';\nimport { DEFAULT_FILENAME } from './constants.js';\nimport { format, Options } from \"prettier\";\n\nexport interface TypeSyncOptions {\n  url: string;\n  token: string;\n  outDir?: string;\n  filename?: string;\n  /** this is used internally to generate the default supported services, you will most definitely need to leave this as true */\n  custom?: boolean;\n  domainWhitelist?: string[];\n  domainBlacklist?: string[];\n  serviceWhitelist?: string[];\n  serviceBlacklist?: string[];\n  prettier?: {\n    options: Options;\n    disable: boolean;\n  }\n}\n\nexport async function typeSync({\n  url,\n  token,\n  outDir: _outDir,\n  filename = DEFAULT_FILENAME,\n  domainWhitelist = [],\n  domainBlacklist = [],\n  serviceWhitelist = [],\n  serviceBlacklist = [],\n  custom = true,\n  prettier,\n}: TypeSyncOptions) {\n  if (!url || !token) {\n    throw new Error('Missing url or token arguments');\n  }\n  const warning = `\n  // this is an auto generated file, do not change this manually\n  `;\n  \n  const { states, services } = await connect(url, token);\n  \n  const serviceInterfaces = await generateActionTypes(services, {\n    domainWhitelist,\n    domainBlacklist,\n    serviceWhitelist,\n    serviceBlacklist,\n  });\n  const output = custom ? `\n    ${warning}\n    import { ServiceFunction, ServiceFunctionTypes } from \"@hakit/core\";\n    declare module '@hakit/core' {\n      export interface CustomSupportedServices<T extends ServiceFunctionTypes = \"target\"> {\n        ${serviceInterfaces}\n      }\n      export interface CustomEntityNameContainer {\n        names: ${generateEntityType(states)};\n      }\n    }\n  ` : `\n    ${warning}\n    import type { ServiceFunctionTypes, ServiceFunction } from \"./\";\n    export interface DefaultServices<T extends ServiceFunctionTypes = \"target\"> {\n      ${serviceInterfaces}\n    }\n  `;\n  const outDir = _outDir || process.cwd();\n  const formatted = prettier?.disable ? output: await format(output, {\n    parser: 'typescript',\n    ...prettier?.options\n  });\n  // now write the file\n  writeFileSync(`${outDir}/${filename}`, formatted);\n  console.info(`Succesfully generated types: ${outDir}/${filename}\\n\\n`);\n  // reminder to add the generated file to the tsconfig.app.json include array\n  console.info(`IMPORTANT: Don't forget to add the \"${filename}\" file to your tsconfig.app.json include array\\n\\n`);\n}"],"names":["MSG_TYPE_AUTH_REQUIRED","MSG_TYPE_AUTH_INVALID","MSG_TYPE_AUTH_OK","ERR_CANNOT_CONNECT","ERR_INVALID_AUTH","createSocket","auth","url","connect","triesLeft","promResolve","promReject","socket","WebSocket","invalidAuth","closeMessage","ev","errorMessage","closeOrError","errMessage","errorText","newTries","handleOpen","err","handleMessage","event","message","resolve","reject","token","createLongLivedTokenAuth","connection","createConnection","services","getServices","states","getStates","DEFAULT_FILENAME","REMAPPED_TYPES","resolveSelectorType","selector","keys","type","options","_","option","sanitizeString","str","generateActionTypes","input","domainWhitelist","domainBlacklist","serviceWhitelist","serviceBlacklist","domain","actions","camelDomain","domainActions","action","fields","description","camelAction","processFields","field","example","rest","required","remapByDomainActionField","remapByActionField","remapByField","domainActionFieldOverride","actionFieldOverride","fieldOverride","_selector","overrides","constraints","ignoredKeys","_key","value","key","exampleUsage","isAdvancedFields","comment","data","actionData","generateEntityType","typeSync","_outDir","filename","custom","prettier","warning","serviceInterfaces","output","outDir","formatted","format","writeFileSync"],"mappings":"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"}