{"version":3,"sources":["../../src/testing/index.ts","../../src/alarm.ts","../../src/types.ts"],"sourcesContent":["import { getChannelAlarmState } from \"../alarm.js\";\nimport type {\n\tActionResult,\n\tAlarm,\n\tArchive,\n\tArchiveChannel,\n\tArchiveListOptions,\n\tDevice,\n\tDeviceChannel,\n\tDeviceEvent,\n\tDeviceFilter,\n\tDeviceHistory,\n\tFirmwareInfo,\n\tHistoricalReading,\n\tMinMaxReading,\n\tTemperatureReading,\n\tThermoworksConfig,\n} from \"../types.js\";\nimport { NotFoundError } from \"../types.js\";\n\nexport type FixtureDemoMode = \"normal\" | \"high\" | \"low\";\ntype FixtureDeviceType = \"node\" | \"signals\" | \"smoke\";\nexport type FixtureFirmwareState = \"up-to-date\" | \"update-available\";\ntype FixtureSerial = \"DEMO-NODE-1CH\" | \"DEMO-OFFLINE-NODE\" | \"DEMO-SIGNALS-4CH\" | \"DEMO-SMOKE-2CH\";\n\nexport interface FixtureFirmwareScenario {\n\treadonly state: FixtureFirmwareState;\n\treadonly deviceType: string;\n\treadonly installedVersion: string;\n\treadonly latest: FirmwareInfo;\n}\n\nexport interface FakeThermoworksCloudOptions {\n\treadonly devices?: readonly Device[];\n\treadonly channels?: Readonly<Record<string, readonly DeviceChannel[]>>;\n\treadonly archives?: Readonly<Record<string, readonly Archive[]>>;\n\treadonly events?: readonly DeviceEvent[];\n\treadonly firmware?: Readonly<Record<string, FirmwareInfo>>;\n}\n\nconst FIXTURE_ACCOUNT_ID = \"demo-account-001\";\nconst NOW = new Date(\"2026-06-01T12:00:00Z\");\nconst FIVE_MIN_AGO = new Date(\"2026-06-01T11:55:00Z\");\nconst TEN_MIN_AGO = new Date(\"2026-06-01T11:50:00Z\");\nconst THIRTY_MIN_AGO = new Date(\"2026-06-01T11:30:00Z\");\nconst TWO_HOURS_AGO = new Date(\"2026-06-01T10:00:00Z\");\nconst ONE_DAY_AGO = new Date(\"2026-05-31T12:00:00Z\");\n\nexport const FIXTURE_LATEST_FIRMWARE: Record<FixtureDeviceType, string> = {\n\tnode: \"3.1.0\",\n\tsignals: \"2.4.1\",\n\tsmoke: \"1.8.3\",\n};\n\nexport const FIXTURE_FIRMWARE: Record<FixtureDeviceType, FirmwareInfo> = {\n\tnode: {\n\t\tname: \"ThermoWorks Node\",\n\t\tversion: FIXTURE_LATEST_FIRMWARE.node,\n\t\tlocation: \"https://fixtures.thermoworks.example/firmware/node-3.1.0.bin\",\n\t\tmd5: \"7f3f5f9f9b97c6b4f2d25a31dbf8f001\",\n\t},\n\tsignals: {\n\t\tname: \"Signals 4-Channel\",\n\t\tversion: FIXTURE_LATEST_FIRMWARE.signals,\n\t\tlocation: \"https://fixtures.thermoworks.example/firmware/signals-2.4.1.bin\",\n\t\tmd5: \"09f7e02f1290be211da707a266f153b3\",\n\t},\n\tsmoke: {\n\t\tname: \"Smoke 2-Channel\",\n\t\tversion: FIXTURE_LATEST_FIRMWARE.smoke,\n\t\tlocation: \"https://fixtures.thermoworks.example/firmware/smoke-1.8.3.bin\",\n\t\tmd5: \"cf9bbf5167f12a4d2b0c88f3a9330004\",\n\t},\n};\n\nexport const FIXTURE_FIRMWARE_SCENARIOS: Record<FixtureFirmwareState, FixtureFirmwareScenario> = {\n\t\"up-to-date\": {\n\t\tstate: \"up-to-date\",\n\t\tdeviceType: \"signals\",\n\t\tinstalledVersion: FIXTURE_LATEST_FIRMWARE.signals,\n\t\tlatest: FIXTURE_FIRMWARE.signals,\n\t},\n\t\"update-available\": {\n\t\tstate: \"update-available\",\n\t\tdeviceType: \"smoke\",\n\t\tinstalledVersion: \"1.5.0\",\n\t\tlatest: FIXTURE_FIRMWARE.smoke,\n\t},\n};\n\nexport function makeAlarm(overrides: Partial<Alarm> = {}): Alarm {\n\treturn {\n\t\tenabled: overrides.enabled ?? true,\n\t\talarming: overrides.alarming ?? false,\n\t\tmuted: overrides.muted ?? false,\n\t\tvalue: overrides.value ?? null,\n\t\tunits: overrides.units ?? \"F\",\n\t\tlastNotified: overrides.lastNotified ?? null,\n\t};\n}\n\nexport function makeMinMaxReading(overrides: Partial<MinMaxReading> = {}): MinMaxReading {\n\treturn {\n\t\tvalue: overrides.value ?? null,\n\t\tunits: overrides.units ?? \"F\",\n\t\tdate: overrides.date ?? null,\n\t};\n}\n\nexport function makeChannel(overrides: Partial<DeviceChannel> = {}): DeviceChannel {\n\treturn {\n\t\tvalue: overrides.value ?? null,\n\t\tunits: overrides.units ?? \"F\",\n\t\tlabel: overrides.label ?? null,\n\t\tstatus: withDefault(overrides, \"status\", \"normal\"),\n\t\ttype: withDefault(overrides, \"type\", \"temperature\"),\n\t\tnumber: withDefault(overrides, \"number\", \"1\"),\n\t\tenabled: withDefault(overrides, \"enabled\", true),\n\t\tcolor: overrides.color ?? null,\n\t\tlastSeen: withDefault(overrides, \"lastSeen\", FIVE_MIN_AGO),\n\t\tlastTelemetrySaved: withDefault(overrides, \"lastTelemetrySaved\", FIVE_MIN_AGO),\n\t\tlastEventId: overrides.lastEventId ?? null,\n\t\tshowAvgTemp: overrides.showAvgTemp ?? false,\n\t\testimatedAlarmStatus: overrides.estimatedAlarmStatus ?? null,\n\t\trateOfChange: overrides.rateOfChange ?? null,\n\t\trateOfChangeUnit: overrides.rateOfChangeUnit ?? null,\n\t\talarmHigh: overrides.alarmHigh ?? null,\n\t\talarmLow: overrides.alarmLow ?? null,\n\t\tminimum: overrides.minimum ?? null,\n\t\tmaximum: overrides.maximum ?? null,\n\t};\n}\n\nexport function makeDevice(overrides: Partial<Device> & { serial: string }): Device {\n\treturn {\n\t\tserial: overrides.serial,\n\t\tdeviceId: overrides.deviceId ?? overrides.serial.toLowerCase(),\n\t\tlabel: overrides.label ?? null,\n\t\ttype: overrides.type ?? null,\n\t\tdevice: overrides.device ?? null,\n\t\tstatus: withDefault(overrides, \"status\", \"online\"),\n\t\tbattery: overrides.battery ?? null,\n\t\tbatteryState: overrides.batteryState ?? null,\n\t\twifiStrength: overrides.wifiStrength ?? null,\n\t\tfirmware: overrides.firmware ?? null,\n\t\tcolor: overrides.color ?? null,\n\t\tthumbnail: overrides.thumbnail ?? null,\n\t\tdeviceDisplayUnits: overrides.deviceDisplayUnits ?? \"F\",\n\t\tiotDeviceId: overrides.iotDeviceId ?? null,\n\t\tiotCoreDeviceBlocked: withDefault(overrides, \"iotCoreDeviceBlocked\", false),\n\t\trecordingIntervalInSeconds: overrides.recordingIntervalInSeconds ?? null,\n\t\ttransmitIntervalInSeconds: overrides.transmitIntervalInSeconds ?? null,\n\t\treadInterval: overrides.readInterval ?? null,\n\t\theartbeatInterval: overrides.heartbeatInterval ?? null,\n\t\ttemperatureDeltaTrigger: overrides.temperatureDeltaTrigger ?? null,\n\t\tpendingLoad: withDefault(overrides, \"pendingLoad\", false),\n\t\tbatteryAlertSent: withDefault(overrides, \"batteryAlertSent\", false),\n\t\tlastSeen: withDefault(overrides, \"lastSeen\", FIVE_MIN_AGO),\n\t\tlastTelemetrySaved: withDefault(overrides, \"lastTelemetrySaved\", FIVE_MIN_AGO),\n\t\tlatestReading: withDefault(overrides, \"latestReading\", FIVE_MIN_AGO),\n\t\tlastWifiConnection: withDefault(overrides, \"lastWifiConnection\", FIVE_MIN_AGO),\n\t\tlastBluetoothConnection: overrides.lastBluetoothConnection ?? null,\n\t\tsessionStart: overrides.sessionStart ?? null,\n\t\tsessionLabel: overrides.sessionLabel ?? null,\n\t\tlastArchive: overrides.lastArchive ?? null,\n\t\tlastPurged: overrides.lastPurged ?? null,\n\t\tassignedToAccountOn: overrides.assignedToAccountOn ?? new Date(\"2024-01-01T00:00:00Z\"),\n\t\taccountId: overrides.accountId ?? FIXTURE_ACCOUNT_ID,\n\t\tnotes: overrides.notes ?? null,\n\t\tpublic: withDefault(overrides, \"public\", false),\n\t\tpublicLink: overrides.publicLink ?? null,\n\t\tsearModeEnabled: withDefault(overrides, \"searModeEnabled\", false),\n\t\tshowSensorChannels: withDefault(overrides, \"showSensorChannels\", true),\n\t\tringColors: overrides.ringColors ?? null,\n\t\tgateway: overrides.gateway ?? null,\n\t\tfan: overrides.fan ?? null,\n\t\tbigQuery: overrides.bigQuery ?? null,\n\t};\n}\n\nexport function makeArchiveChannel(overrides: Partial<ArchiveChannel> = {}): ArchiveChannel {\n\tconst readings =\n\t\toverrides.recentReadings ??\n\t\tmakeTemperatureReadings(overrides.value ?? 225, overrides.units ?? \"F\");\n\tconst values = readings.map((reading) => reading.value);\n\treturn {\n\t\tnumber: overrides.number ?? \"1\",\n\t\tlabel: overrides.label ?? \"Pit\",\n\t\tunits: overrides.units ?? \"F\",\n\t\tvalue: overrides.value ?? values.at(-1) ?? null,\n\t\tstatus: overrides.status ?? \"normal\",\n\t\tenabled: overrides.enabled ?? true,\n\t\tcolor: overrides.color ?? null,\n\t\ttype: overrides.type ?? \"temperature\",\n\t\talarmHigh: overrides.alarmHigh ?? null,\n\t\talarmLow: overrides.alarmLow ?? null,\n\t\tminimum:\n\t\t\toverrides.minimum ??\n\t\t\tmakeMinMaxReading({\n\t\t\t\tvalue: Math.min(...values),\n\t\t\t\tunits: overrides.units ?? \"F\",\n\t\t\t\tdate: ONE_DAY_AGO,\n\t\t\t}),\n\t\tmaximum:\n\t\t\toverrides.maximum ??\n\t\t\tmakeMinMaxReading({ value: Math.max(...values), units: overrides.units ?? \"F\", date: NOW }),\n\t\trecentReadings: readings,\n\t};\n}\n\nexport function makeArchive(overrides: Partial<Archive> & { id?: string } = {}): Archive {\n\treturn {\n\t\tid: overrides.id ?? \"fixture-archive-001\",\n\t\tstart: overrides.start ?? TWO_HOURS_AGO,\n\t\tend: overrides.end ?? NOW,\n\t\tcount: overrides.count ?? 5,\n\t\ttype: overrides.type ?? \"session\",\n\t\tlabel: overrides.label ?? \"Sunday Brisket\",\n\t\tdeviceLabel: overrides.deviceLabel ?? \"Backyard Smoker\",\n\t\tnotes: overrides.notes ?? \"Synthetic offline fixture session\",\n\t\tcreatedOn: overrides.createdOn ?? NOW,\n\t\tpublic: overrides.public ?? false,\n\t\tpublicLink: overrides.publicLink ?? null,\n\t\tfilename: overrides.filename ?? null,\n\t\tchannels: overrides.channels ?? [makeArchiveChannel()],\n\t};\n}\n\nfunction makeTemperatureReadings(finalValue: number, units: string): TemperatureReading[] {\n\treturn [\n\t\t{ value: finalValue - 8, timestamp: new Date(\"2026-06-01T10:00:00Z\"), units },\n\t\t{ value: finalValue - 3, timestamp: new Date(\"2026-06-01T11:00:00Z\"), units },\n\t\t{ value: finalValue, timestamp: NOW, units },\n\t];\n}\n\nexport const FIXTURE_DEVICES: Device[] = [\n\tmakeDevice({\n\t\tserial: \"DEMO-SIGNALS-4CH\",\n\t\tdeviceId: \"signals-001\",\n\t\tlabel: \"Backyard Smoker\",\n\t\ttype: \"signals\",\n\t\tdevice: \"Signals 4-Channel\",\n\t\tstatus: \"online\",\n\t\tbattery: 87,\n\t\tbatteryState: \"normal\",\n\t\twifiStrength: -42,\n\t\tfirmware: FIXTURE_LATEST_FIRMWARE.signals,\n\t\tcolor: \"#FF6B35\",\n\t\tiotDeviceId: \"iot-signals-001\",\n\t\trecordingIntervalInSeconds: 2,\n\t\ttransmitIntervalInSeconds: 10,\n\t\treadInterval: 2,\n\t\theartbeatInterval: 60,\n\t\ttemperatureDeltaTrigger: 1,\n\t\tsessionStart: TWO_HOURS_AGO,\n\t\tsessionLabel: \"Sunday Brisket\",\n\t\tassignedToAccountOn: new Date(\"2024-03-15T00:00:00Z\"),\n\t\tringColors: [\"#FF6B35\", \"#4ECDC4\", \"#FFE66D\", \"#95E1D3\"],\n\t}),\n\tmakeDevice({\n\t\tserial: \"DEMO-SMOKE-2CH\",\n\t\tdeviceId: \"smoke-001\",\n\t\tlabel: \"Easter Brisket\",\n\t\ttype: \"smoke\",\n\t\tdevice: \"Smoke 2-Channel\",\n\t\tstatus: \"online\",\n\t\tbattery: 62,\n\t\tbatteryState: \"normal\",\n\t\twifiStrength: -55,\n\t\tfirmware: FIXTURE_FIRMWARE_SCENARIOS[\"update-available\"].installedVersion,\n\t\tcolor: \"#4ECDC4\",\n\t\tiotDeviceId: \"iot-smoke-001\",\n\t\trecordingIntervalInSeconds: 3,\n\t\ttransmitIntervalInSeconds: 15,\n\t\treadInterval: 3,\n\t\theartbeatInterval: 60,\n\t\ttemperatureDeltaTrigger: 1,\n\t\tlastSeen: TEN_MIN_AGO,\n\t\tlastTelemetrySaved: TEN_MIN_AGO,\n\t\tlatestReading: TEN_MIN_AGO,\n\t\tlastWifiConnection: TEN_MIN_AGO,\n\t\tsessionStart: TWO_HOURS_AGO,\n\t\tsessionLabel: \"Easter Brisket\",\n\t\tassignedToAccountOn: new Date(\"2023-11-20T00:00:00Z\"),\n\t\tringColors: [\"#4ECDC4\", \"#FFE66D\"],\n\t}),\n\tmakeDevice({\n\t\tserial: \"DEMO-NODE-1CH\",\n\t\tdeviceId: \"node-001\",\n\t\tlabel: \"Garage Fridge\",\n\t\ttype: \"node\",\n\t\tdevice: \"ThermoWorks Node\",\n\t\tstatus: \"online\",\n\t\tbattery: 94,\n\t\tbatteryState: \"normal\",\n\t\twifiStrength: -38,\n\t\tfirmware: FIXTURE_LATEST_FIRMWARE.node,\n\t\tcolor: \"#6C5CE7\",\n\t\tiotDeviceId: \"iot-node-001\",\n\t\trecordingIntervalInSeconds: 30,\n\t\ttransmitIntervalInSeconds: 60,\n\t\treadInterval: 30,\n\t\theartbeatInterval: 300,\n\t\ttemperatureDeltaTrigger: 2,\n\t\tassignedToAccountOn: new Date(\"2024-06-01T00:00:00Z\"),\n\t\tnotes: \"Monitoring garage fridge temp\",\n\t\tshowSensorChannels: false,\n\t}),\n\tmakeDevice({\n\t\tserial: \"DEMO-OFFLINE-NODE\",\n\t\tdeviceId: \"node-offline-001\",\n\t\tlabel: \"Basement Freezer\",\n\t\ttype: \"node\",\n\t\tdevice: \"ThermoWorks Node\",\n\t\tstatus: \"offline\",\n\t\tbattery: 18,\n\t\tbatteryState: \"low\",\n\t\twifiStrength: -85,\n\t\tfirmware: \"3.0.0\",\n\t\tcolor: \"#A29BFE\",\n\t\tlastSeen: ONE_DAY_AGO,\n\t\tlastTelemetrySaved: ONE_DAY_AGO,\n\t\tlatestReading: ONE_DAY_AGO,\n\t\tlastWifiConnection: ONE_DAY_AGO,\n\t\tassignedToAccountOn: new Date(\"2024-07-01T00:00:00Z\"),\n\t\tnotes: \"Offline fixture for stale device states\",\n\t\tshowSensorChannels: false,\n\t}),\n];\n\nfunction activeAlarm(value: number): Alarm {\n\treturn makeAlarm({ alarming: true, value, lastNotified: NOW });\n}\n\nconst inactiveAlarm = (value: number): Alarm => makeAlarm({ alarming: false, value });\n\nexport function getFixtureChannels(\n\tserial: string,\n\tmode: FixtureDemoMode = \"normal\",\n): DeviceChannel[] {\n\tconst channels =\n\t\tserial in FIXTURE_CHANNELS ? FIXTURE_CHANNELS[serial as FixtureSerial][mode] : [];\n\treturn clone(channels);\n}\n\nexport const FIXTURE_CHANNELS: Record<FixtureSerial, Record<FixtureDemoMode, DeviceChannel[]>> = {\n\t\"DEMO-NODE-1CH\": {\n\t\thigh: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Internal\",\n\t\t\t\tvalue: 48,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#6C5CE7\",\n\t\t\t\talarmHigh: activeAlarm(45),\n\t\t\t\talarmLow: inactiveAlarm(32),\n\t\t\t}),\n\t\t],\n\t\tlow: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Internal\",\n\t\t\t\tvalue: 28,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#6C5CE7\",\n\t\t\t\talarmHigh: inactiveAlarm(45),\n\t\t\t\talarmLow: activeAlarm(32),\n\t\t\t}),\n\t\t],\n\t\tnormal: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Internal\",\n\t\t\t\tvalue: 38,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#6C5CE7\",\n\t\t\t\talarmHigh: inactiveAlarm(45),\n\t\t\t\talarmLow: inactiveAlarm(32),\n\t\t\t}),\n\t\t],\n\t},\n\t\"DEMO-OFFLINE-NODE\": {\n\t\thigh: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Internal\",\n\t\t\t\tvalue: null,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tstatus: \"offline\",\n\t\t\t\tcolor: \"#A29BFE\",\n\t\t\t\tlastSeen: ONE_DAY_AGO,\n\t\t\t\tlastTelemetrySaved: ONE_DAY_AGO,\n\t\t\t\talarmHigh: inactiveAlarm(45),\n\t\t\t\talarmLow: inactiveAlarm(0),\n\t\t\t}),\n\t\t],\n\t\tlow: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Internal\",\n\t\t\t\tvalue: null,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tstatus: \"offline\",\n\t\t\t\tcolor: \"#A29BFE\",\n\t\t\t\tlastSeen: ONE_DAY_AGO,\n\t\t\t\tlastTelemetrySaved: ONE_DAY_AGO,\n\t\t\t\talarmHigh: inactiveAlarm(45),\n\t\t\t\talarmLow: inactiveAlarm(0),\n\t\t\t}),\n\t\t],\n\t\tnormal: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Internal\",\n\t\t\t\tvalue: null,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tstatus: \"offline\",\n\t\t\t\tcolor: \"#A29BFE\",\n\t\t\t\tlastSeen: ONE_DAY_AGO,\n\t\t\t\tlastTelemetrySaved: ONE_DAY_AGO,\n\t\t\t\talarmHigh: inactiveAlarm(45),\n\t\t\t\talarmLow: inactiveAlarm(0),\n\t\t\t}),\n\t\t],\n\t},\n\t\"DEMO-SIGNALS-4CH\": {\n\t\thigh: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Pit\",\n\t\t\t\tvalue: 285,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#FF6B35\",\n\t\t\t\talarmHigh: activeAlarm(275),\n\t\t\t\talarmLow: inactiveAlarm(200),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Brisket\",\n\t\t\t\tvalue: 205,\n\t\t\t\tnumber: \"2\",\n\t\t\t\tcolor: \"#4ECDC4\",\n\t\t\t\talarmHigh: activeAlarm(203),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Ribs\",\n\t\t\t\tvalue: 198,\n\t\t\t\tnumber: \"3\",\n\t\t\t\tcolor: \"#FFE66D\",\n\t\t\t\talarmHigh: inactiveAlarm(200),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Ambient\",\n\t\t\t\tvalue: 72,\n\t\t\t\tnumber: \"4\",\n\t\t\t\tcolor: \"#95E1D3\",\n\t\t\t\talarmHigh: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t],\n\t\tlow: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Pit\",\n\t\t\t\tvalue: 180,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#FF6B35\",\n\t\t\t\talarmHigh: inactiveAlarm(275),\n\t\t\t\talarmLow: activeAlarm(200),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Brisket\",\n\t\t\t\tvalue: 120,\n\t\t\t\tnumber: \"2\",\n\t\t\t\tcolor: \"#4ECDC4\",\n\t\t\t\talarmHigh: inactiveAlarm(203),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Ribs\",\n\t\t\t\tvalue: 175,\n\t\t\t\tnumber: \"3\",\n\t\t\t\tcolor: \"#FFE66D\",\n\t\t\t\talarmHigh: inactiveAlarm(200),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Ambient\",\n\t\t\t\tvalue: 72,\n\t\t\t\tnumber: \"4\",\n\t\t\t\tcolor: \"#95E1D3\",\n\t\t\t\talarmHigh: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t],\n\t\tnormal: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Pit\",\n\t\t\t\tvalue: 225,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#FF6B35\",\n\t\t\t\talarmHigh: inactiveAlarm(275),\n\t\t\t\talarmLow: inactiveAlarm(200),\n\t\t\t\tminimum: makeMinMaxReading({ value: 220, date: THIRTY_MIN_AGO }),\n\t\t\t\tmaximum: makeMinMaxReading({ value: 235, date: TEN_MIN_AGO }),\n\t\t\t\trateOfChange: 1.2,\n\t\t\t\trateOfChangeUnit: \"F/min\",\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Brisket\",\n\t\t\t\tvalue: 168,\n\t\t\t\tnumber: \"2\",\n\t\t\t\tcolor: \"#4ECDC4\",\n\t\t\t\talarmHigh: inactiveAlarm(203),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Ribs\",\n\t\t\t\tvalue: 175,\n\t\t\t\tnumber: \"3\",\n\t\t\t\tcolor: \"#FFE66D\",\n\t\t\t\talarmHigh: inactiveAlarm(200),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Ambient\",\n\t\t\t\tvalue: 72,\n\t\t\t\tnumber: \"4\",\n\t\t\t\tcolor: \"#95E1D3\",\n\t\t\t\talarmHigh: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t],\n\t},\n\t\"DEMO-SMOKE-2CH\": {\n\t\thigh: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Pit\",\n\t\t\t\tvalue: 292,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#4ECDC4\",\n\t\t\t\talarmHigh: activeAlarm(285),\n\t\t\t\talarmLow: inactiveAlarm(220),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Brisket\",\n\t\t\t\tvalue: 207,\n\t\t\t\tnumber: \"2\",\n\t\t\t\tcolor: \"#FFE66D\",\n\t\t\t\talarmHigh: activeAlarm(203),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t],\n\t\tlow: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Pit\",\n\t\t\t\tvalue: 208,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#4ECDC4\",\n\t\t\t\talarmHigh: inactiveAlarm(285),\n\t\t\t\talarmLow: activeAlarm(220),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Brisket\",\n\t\t\t\tvalue: 168,\n\t\t\t\tnumber: \"2\",\n\t\t\t\tcolor: \"#FFE66D\",\n\t\t\t\talarmHigh: inactiveAlarm(203),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t],\n\t\tnormal: [\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Pit\",\n\t\t\t\tvalue: 250,\n\t\t\t\tnumber: \"1\",\n\t\t\t\tcolor: \"#4ECDC4\",\n\t\t\t\talarmHigh: inactiveAlarm(285),\n\t\t\t\talarmLow: inactiveAlarm(220),\n\t\t\t}),\n\t\t\tmakeChannel({\n\t\t\t\tlabel: \"Brisket\",\n\t\t\t\tvalue: 168,\n\t\t\t\tnumber: \"2\",\n\t\t\t\tcolor: \"#FFE66D\",\n\t\t\t\talarmHigh: inactiveAlarm(203),\n\t\t\t\talarmLow: makeAlarm({ enabled: false, value: null, units: null }),\n\t\t\t}),\n\t\t],\n\t},\n};\n\nexport const FIXTURE_ARCHIVES: Record<FixtureSerial, Archive[]> = {\n\t\"DEMO-NODE-1CH\": [\n\t\tmakeArchive({\n\t\t\tid: \"demo-DEMO-NODE-1CH-0\",\n\t\t\tlabel: \"Garage Fridge\",\n\t\t\tdeviceLabel: \"Garage Fridge\",\n\t\t\tchannels: [\n\t\t\t\tmakeArchiveChannel({\n\t\t\t\t\tlabel: \"Internal\",\n\t\t\t\t\tnumber: \"1\",\n\t\t\t\t\tvalue: 38,\n\t\t\t\t\tcolor: \"#6C5CE7\",\n\t\t\t\t\talarmHigh: inactiveAlarm(45),\n\t\t\t\t\talarmLow: inactiveAlarm(32),\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t],\n\t\"DEMO-OFFLINE-NODE\": [\n\t\tmakeArchive({\n\t\t\tid: \"demo-DEMO-OFFLINE-NODE-0\",\n\t\t\tlabel: \"Freezer Check\",\n\t\t\tdeviceLabel: \"Basement Freezer\",\n\t\t\tchannels: [\n\t\t\t\tmakeArchiveChannel({\n\t\t\t\t\tlabel: \"Internal\",\n\t\t\t\t\tnumber: \"1\",\n\t\t\t\t\tvalue: 2,\n\t\t\t\t\tcolor: \"#A29BFE\",\n\t\t\t\t\talarmHigh: inactiveAlarm(45),\n\t\t\t\t\talarmLow: inactiveAlarm(0),\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t],\n\t\"DEMO-SIGNALS-4CH\": [\n\t\tmakeArchive({\n\t\t\tid: \"demo-DEMO-SIGNALS-4CH-0\",\n\t\t\tlabel: \"Sunday Brisket\",\n\t\t\tdeviceLabel: \"Backyard Smoker\",\n\t\t\tchannels: FIXTURE_CHANNELS[\"DEMO-SIGNALS-4CH\"].normal.slice(0, 3).map((channel) =>\n\t\t\t\tmakeArchiveChannel({\n\t\t\t\t\talarmHigh: channel.alarmHigh,\n\t\t\t\t\talarmLow: channel.alarmLow,\n\t\t\t\t\tcolor: channel.color,\n\t\t\t\t\tlabel: channel.label,\n\t\t\t\t\tnumber: channel.number,\n\t\t\t\t\tvalue: channel.value,\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t\tmakeArchive({\n\t\t\tid: \"demo-DEMO-SIGNALS-4CH-1\",\n\t\t\tlabel: \"Grilled Steak\",\n\t\t\tdeviceLabel: \"Backyard Smoker\",\n\t\t\tstart: new Date(\"2026-05-30T18:00:00Z\"),\n\t\t\tend: new Date(\"2026-05-30T18:24:00Z\"),\n\t\t\tchannels: [\n\t\t\t\tmakeArchiveChannel({\n\t\t\t\t\tlabel: \"Grill\",\n\t\t\t\t\tnumber: \"1\",\n\t\t\t\t\tvalue: 515,\n\t\t\t\t\tcolor: \"#FF6B35\",\n\t\t\t\t\talarmHigh: inactiveAlarm(525),\n\t\t\t\t}),\n\t\t\t\tmakeArchiveChannel({\n\t\t\t\t\tlabel: \"Steak\",\n\t\t\t\t\tnumber: \"2\",\n\t\t\t\t\tvalue: 125,\n\t\t\t\t\tcolor: \"#E84855\",\n\t\t\t\t\talarmHigh: inactiveAlarm(125),\n\t\t\t\t}),\n\t\t\t],\n\t\t}),\n\t],\n\t\"DEMO-SMOKE-2CH\": [\n\t\tmakeArchive({\n\t\t\tid: \"demo-DEMO-SMOKE-2CH-0\",\n\t\t\tlabel: \"Easter Brisket\",\n\t\t\tdeviceLabel: \"Easter Brisket\",\n\t\t\tchannels: FIXTURE_CHANNELS[\"DEMO-SMOKE-2CH\"].normal.map((channel) =>\n\t\t\t\tmakeArchiveChannel({\n\t\t\t\t\talarmHigh: channel.alarmHigh,\n\t\t\t\t\talarmLow: channel.alarmLow,\n\t\t\t\t\tcolor: channel.color,\n\t\t\t\t\tlabel: channel.label,\n\t\t\t\t\tnumber: channel.number,\n\t\t\t\t\tvalue: channel.value,\n\t\t\t\t}),\n\t\t\t),\n\t\t}),\n\t],\n};\n\nexport const HIGH_ALARM_CHANNEL = firstChannel(FIXTURE_CHANNELS[\"DEMO-SIGNALS-4CH\"].high);\nexport const LOW_ALARM_CHANNEL = firstChannel(FIXTURE_CHANNELS[\"DEMO-NODE-1CH\"].low);\nexport const OFFLINE_DEVICE = FIXTURE_DEVICES.find(\n\t(device) => device.status === \"offline\",\n) as Device;\n\nexport class FakeThermoworksCloud {\n\tprivate readonly devices: Device[];\n\tprivate readonly channels: Record<string, DeviceChannel[]>;\n\tprivate readonly archives: Record<string, Archive[]>;\n\tprivate readonly events: DeviceEvent[];\n\tprivate readonly firmware: Record<string, FirmwareInfo>;\n\treadonly config: ThermoworksConfig | null;\n\tclosed = false;\n\n\tconstructor(config: ThermoworksConfig | null = null, options: FakeThermoworksCloudOptions = {}) {\n\t\tthis.config = config;\n\t\tthis.devices = clone([...(options.devices ?? FIXTURE_DEVICES)]);\n\t\tthis.channels = clone(\n\t\t\ttoMutableRecord(\n\t\t\t\toptions.channels ??\n\t\t\t\t\tObject.fromEntries(\n\t\t\t\t\t\tObject.entries(FIXTURE_CHANNELS).map(([serial, modes]) => [serial, modes.normal]),\n\t\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tthis.archives = clone(toMutableRecord(options.archives ?? FIXTURE_ARCHIVES));\n\t\tthis.events = clone([...(options.events ?? makeFixtureEvents())]);\n\t\tthis.firmware = clone({ ...(options.firmware ?? FIXTURE_FIRMWARE) });\n\t}\n\n\tasync getDevices(filter?: DeviceFilter): Promise<Device[]> {\n\t\treturn applyFilter(clone(this.devices), filter);\n\t}\n\n\tasync getDevice(serial: string): Promise<Device> {\n\t\tconst device = this.devices.find((candidate) => candidate.serial === serial);\n\t\tif (!device) throw new NotFoundError(`Device with serial '${serial}' not found`);\n\t\treturn clone(device);\n\t}\n\n\tasync getAllDeviceChannels(serial: string): Promise<DeviceChannel[]> {\n\t\treturn clone(this.channels[serial] ?? []);\n\t}\n\n\tasync getDeviceChannel(serial: string, channel: number): Promise<DeviceChannel> {\n\t\tconst found = this.channels[serial]?.find((candidate) => candidate.number === String(channel));\n\t\tif (!found) throw new NotFoundError(`Channel ${channel} for device '${serial}' not found`);\n\t\treturn clone(found);\n\t}\n\n\tasync getAverageTemperature(serial: string): Promise<{ value: number; units: string } | null> {\n\t\tconst readings = (this.channels[serial] ?? []).filter(\n\t\t\t(channel) => channel.enabled !== false && channel.units === \"F\" && channel.value != null,\n\t\t);\n\t\tif (readings.length === 0) return null;\n\t\tconst total = readings.reduce((sum, channel) => sum + (channel.value ?? 0), 0);\n\t\treturn { value: Math.round((total / readings.length) * 10) / 10, units: \"F\" };\n\t}\n\n\tasync getArchives(serial: string, options: ArchiveListOptions = {}): Promise<Archive[]> {\n\t\treturn clone((this.archives[serial] ?? []).slice(0, options.limit ?? undefined));\n\t}\n\n\tasync getArchive(serial: string, archiveId: string): Promise<Archive> {\n\t\tconst archive = this.archives[serial]?.find((candidate) => candidate.id === archiveId);\n\t\tif (!archive)\n\t\t\tthrow new NotFoundError(`Archive '${archiveId}' for device '${serial}' not found`);\n\t\treturn clone(archive);\n\t}\n\n\tasync getEvents(filter: { deviceId?: string; limit?: number } = {}): Promise<DeviceEvent[]> {\n\t\tconst events = filter.deviceId\n\t\t\t? this.events.filter((event) => event.deviceId === filter.deviceId)\n\t\t\t: this.events;\n\t\treturn clone(events.slice(0, filter.limit ?? undefined));\n\t}\n\n\tasync getFirmwareInfo(deviceType: string): Promise<FirmwareInfo> {\n\t\tconst info = this.firmware[deviceType];\n\t\tif (!info) throw new NotFoundError(`Firmware for device type '${deviceType}' not found`);\n\t\treturn clone(info);\n\t}\n\n\tasync getHistory(serial: string): Promise<DeviceHistory> {\n\t\tconst readings: HistoricalReading[] = (this.archives[serial]?.[0]?.channels ?? []).flatMap(\n\t\t\t(channel) =>\n\t\t\t\tchannel.recentReadings.map((reading) => ({\n\t\t\t\t\ttimestamp: reading.timestamp.toISOString(),\n\t\t\t\t\tunits: reading.units,\n\t\t\t\t\tvalue: reading.value,\n\t\t\t\t})),\n\t\t);\n\t\treturn { deviceId: serial, readings };\n\t}\n\n\tasync startSession(serial: string, label = \"Fixture Session\"): Promise<ActionResult> {\n\t\tconst device = this.devices.find((candidate) => candidate.serial === serial);\n\t\tif (device) {\n\t\t\tObject.assign(device, { sessionLabel: label, sessionStart: NOW });\n\t\t}\n\t\treturn { success: true, data: { serial, label }, error: null };\n\t}\n\n\tasync endSession(serial: string): Promise<ActionResult> {\n\t\tconst device = this.devices.find((candidate) => candidate.serial === serial);\n\t\tif (device) {\n\t\t\tObject.assign(device, { sessionLabel: null, sessionStart: null });\n\t\t}\n\t\treturn { success: true, data: { serial }, error: null };\n\t}\n\n\tasync setAlarm(\n\t\tserial: string,\n\t\tchannelNumber: number,\n\t\tconfig: {\n\t\t\thigh?: { value: number; units?: string; enabled?: boolean; muted?: boolean };\n\t\t\tlow?: { value: number; units?: string; enabled?: boolean; muted?: boolean };\n\t\t},\n\t): Promise<void> {\n\t\tconst channel = this.channels[serial]?.find(\n\t\t\t(candidate) => candidate.number === String(channelNumber),\n\t\t);\n\t\tif (!channel)\n\t\t\tthrow new NotFoundError(`Channel ${channelNumber} for device '${serial}' not found`);\n\t\tif (config.high) {\n\t\t\tObject.assign(channel, { alarmHigh: makeAlarm({ ...config.high, alarming: false }) });\n\t\t}\n\t\tif (config.low) {\n\t\t\tObject.assign(channel, { alarmLow: makeAlarm({ ...config.low, alarming: false }) });\n\t\t}\n\t}\n\n\tclose(): void {\n\t\tthis.closed = true;\n\t}\n}\n\nfunction makeFixtureEvents(): DeviceEvent[] {\n\treturn [\n\t\t{\n\t\t\tid: \"fixture-event-high\",\n\t\t\teventType: \"High Alarm\",\n\t\t\tseverity: 2,\n\t\t\teventTime: NOW,\n\t\t\tdeviceId: \"DEMO-SIGNALS-4CH\",\n\t\t\tchannelId: \"1\",\n\t\t\taccountId: FIXTURE_ACCOUNT_ID,\n\t\t\tvalueBefore: \"270\",\n\t\t\tvalueAfter: \"285\",\n\t\t\tgroups: [\"bbq\"],\n\t\t},\n\t\t{\n\t\t\tid: \"fixture-event-low\",\n\t\t\teventType: \"Low Alarm\",\n\t\t\tseverity: 2,\n\t\t\teventTime: NOW,\n\t\t\tdeviceId: \"DEMO-NODE-1CH\",\n\t\t\tchannelId: \"1\",\n\t\t\taccountId: FIXTURE_ACCOUNT_ID,\n\t\t\tvalueBefore: \"34\",\n\t\t\tvalueAfter: \"28\",\n\t\t\tgroups: [\"storage\"],\n\t\t},\n\t];\n}\n\nfunction applyFilter(devices: Device[], filter?: DeviceFilter): Device[] {\n\tif (!filter) return devices;\n\treturn devices.filter((device) => {\n\t\tif (filter.serial && !matches(device.serial, filter.serial)) return false;\n\t\tif (filter.type && !matches(device.type, filter.type)) return false;\n\t\tif (filter.label && !matches(device.label, filter.label)) return false;\n\t\tif (filter.status && !matches(device.status, filter.status)) return false;\n\t\tif (filter.activeWithinMinutes != null) {\n\t\t\tif (!device.lastSeen) return false;\n\t\t\tconst ageMinutes = (NOW.getTime() - device.lastSeen.getTime()) / 60_000;\n\t\t\tif (ageMinutes > filter.activeWithinMinutes) return false;\n\t\t}\n\t\treturn true;\n\t});\n}\n\nfunction matches(value: string | null, expected: string | string[]): boolean {\n\tconst values = Array.isArray(expected) ? expected : [expected];\n\treturn value != null && values.includes(value);\n}\n\nfunction withDefault<T, K extends keyof T>(\n\toverrides: Partial<T>,\n\tkey: K,\n\tfallback: NonNullable<T[K]>,\n): T[K] {\n\treturn Object.hasOwn(overrides, key) ? (overrides[key] as T[K]) : fallback;\n}\n\nfunction firstChannel(channels: DeviceChannel[]): DeviceChannel {\n\tconst [channel] = channels;\n\tif (!channel) {\n\t\tthrow new Error(\"Fixture channel list is empty\");\n\t}\n\treturn channel;\n}\n\nfunction clone<T>(value: T): T {\n\treturn structuredClone(value);\n}\n\nfunction toMutableRecord<T>(record: Readonly<Record<string, readonly T[]>>): Record<string, T[]> {\n\treturn Object.fromEntries(Object.entries(record).map(([key, value]) => [key, [...value]]));\n}\n\nexport function getFixtureAlarmState(channel: DeviceChannel): \"none\" | \"high\" | \"low\" {\n\treturn getChannelAlarmState(channel);\n}\n","import type { DeviceChannel } from \"./types.js\";\n\n/** Alarm severity state for a device or channel. */\nexport type AlarmState = \"none\" | \"low\" | \"high\";\n\n/** Determine the alarm state of a single channel. */\nexport function getChannelAlarmState(channel: DeviceChannel): AlarmState {\n\tif (channel.alarmHigh?.alarming) return \"high\";\n\tif (channel.alarmLow?.alarming) return \"low\";\n\treturn \"none\";\n}\n\n/** Determine the highest alarm state across multiple channels. */\nexport function getChannelsAlarmState(channels: DeviceChannel[]): AlarmState {\n\tfor (const ch of channels) {\n\t\tif (ch.alarmHigh?.alarming) return \"high\";\n\t}\n\tfor (const ch of channels) {\n\t\tif (ch.alarmLow?.alarming) return \"low\";\n\t}\n\treturn \"none\";\n}\n\n/** Escalate to the more severe of two alarm states. */\nexport function escalateAlarm(current: AlarmState, incoming: AlarmState): AlarmState {\n\tif (current === \"high\" || incoming === \"high\") return \"high\";\n\tif (current === \"low\" || incoming === \"low\") return \"low\";\n\treturn \"none\";\n}\n","/** Configuration for automatic retry with exponential backoff. */\nexport interface RetryConfig {\n\t/** Maximum number of retry attempts (default 3). */\n\tmaxRetries?: number;\n\t/** Base delay in milliseconds before exponential increase (default 1000). */\n\tbaseDelayMs?: number;\n\t/** Maximum delay in milliseconds between retries (default 30000). */\n\tmaxDelayMs?: number;\n}\n\n/** Configuration for the ThermoWorks Cloud client. */\nexport interface ThermoworksConfig {\n\t/** ThermoWorks Cloud account email address. */\n\temail: string;\n\t/** ThermoWorks Cloud account password. */\n\tpassword: string;\n\t/** Override the default Firebase API key. */\n\tapiKey?: string;\n\t/** Override the default Firebase app ID. */\n\tappId?: string;\n\t/** Retry configuration for transient failures (429, 503, network errors). */\n\tretry?: RetryConfig;\n\t/**\n\t * Path to the token cache file for persisting auth tokens across sessions.\n\t * Reduces authentication overhead by reusing valid tokens instead of\n\t * performing a full sign-in on every client instantiation.\n\t *\n\t * Defaults to `~/.thermoworks/.token-cache.json` if set to `true` or a string path.\n\t * Set to `false` or omit to disable token caching.\n\t */\n\ttokenCachePath?: string | boolean;\n}\n\n// ─── Device ──────────────────────────────────────────────────────────────────\n\n/** A ThermoWorks device (Node, Smoke, Signals, RFX Gateway, etc). */\nexport interface Device {\n\treadonly serial: string;\n\treadonly deviceId: string | null;\n\treadonly label: string | null;\n\treadonly type: string | null;\n\treadonly device: string | null;\n\treadonly status: string | null;\n\treadonly battery: number | null;\n\treadonly batteryState: string | null;\n\treadonly wifiStrength: number | null;\n\treadonly firmware: string | null;\n\treadonly color: string | null;\n\treadonly thumbnail: string | null;\n\treadonly deviceDisplayUnits: string | null;\n\treadonly iotDeviceId: string | null;\n\treadonly iotCoreDeviceBlocked: boolean | null;\n\treadonly recordingIntervalInSeconds: number | null;\n\treadonly transmitIntervalInSeconds: number | null;\n\treadonly readInterval: number | null;\n\treadonly heartbeatInterval: number | null;\n\treadonly temperatureDeltaTrigger: number | null;\n\treadonly pendingLoad: boolean | null;\n\treadonly batteryAlertSent: boolean | null;\n\treadonly lastSeen: Date | null;\n\treadonly lastTelemetrySaved: Date | null;\n\treadonly latestReading: Date | null;\n\treadonly lastWifiConnection: Date | null;\n\treadonly lastBluetoothConnection: Date | null;\n\treadonly sessionStart: Date | null;\n\treadonly sessionLabel: string | null;\n\treadonly lastArchive: Date | null;\n\treadonly lastPurged: Date | null;\n\treadonly assignedToAccountOn: Date | null;\n\treadonly accountId: string | null;\n\treadonly notes: string | null;\n\treadonly public: boolean | null;\n\treadonly publicLink: string | null;\n\treadonly searModeEnabled: boolean | null;\n\treadonly showSensorChannels: boolean | null;\n\treadonly ringColors: string[] | null;\n\treadonly gateway: GatewayInfo | null;\n\treadonly fan: FanSettings | null;\n\treadonly bigQuery: BigQueryRef | null;\n}\n\n/** Gateway connection info for RFX wireless devices. */\nexport interface GatewayInfo {\n\treadonly gatewayId: string | null;\n\treadonly rssi: number | null;\n\treadonly lastSeen: Date | null;\n\treadonly switchedAt: Date | null;\n\treadonly lastPacketId: number | null;\n}\n\n/** BBQ fan/blower controller settings. */\nexport interface FanSettings {\n\treadonly connected: boolean;\n\treadonly connection: boolean;\n\treadonly setTemp: number | null;\n\treadonly fanChannel: string | null;\n\treadonly state: number | null;\n}\n\n/** Reference to historical data in BigQuery. */\nexport interface BigQueryRef {\n\treadonly datasetId: string;\n\treadonly tableId: string;\n}\n\n// ─── Channel ─────────────────────────────────────────────────────────────────\n\n/** A channel reading from a device (temperature or humidity sensor). */\nexport interface DeviceChannel {\n\treadonly value: number | null;\n\treadonly units: string | null;\n\treadonly label: string | null;\n\treadonly status: string | null;\n\treadonly type: string | null;\n\treadonly number: string | null;\n\treadonly enabled: boolean | null;\n\treadonly color: string | null;\n\treadonly lastSeen: Date | null;\n\treadonly lastTelemetrySaved: Date | null;\n\treadonly lastEventId: string | null;\n\treadonly showAvgTemp: boolean | null;\n\treadonly estimatedAlarmStatus: string | null;\n\treadonly rateOfChange: number | null;\n\treadonly rateOfChangeUnit: string | null;\n\treadonly alarmHigh: Alarm | null;\n\treadonly alarmLow: Alarm | null;\n\treadonly minimum: MinMaxReading | null;\n\treadonly maximum: MinMaxReading | null;\n}\n\n/** An alarm threshold on a device channel. */\nexport interface Alarm {\n\treadonly enabled: boolean;\n\treadonly alarming: boolean;\n\treadonly muted: boolean | null;\n\treadonly value: number | null;\n\treadonly units: string | null;\n\treadonly lastNotified: Date | null;\n}\n\n/** A minimum or maximum reading record. */\nexport interface MinMaxReading {\n\treadonly value: number | null;\n\treadonly units: string | null;\n\treadonly date: Date | null;\n}\n\n// ─── User ────────────────────────────────────────────────────────────────────\n\n/** User account information. */\nexport interface User {\n\treadonly userId: string;\n\treadonly accountId: string | null;\n\treadonly email: string | null;\n\treadonly displayName: string | null;\n\treadonly timeZone: string | null;\n\treadonly preferredUnits: string | null;\n\treadonly locale: string | null;\n\treadonly photoUrl: string | null;\n\treadonly use24Time: boolean | null;\n\treadonly lastLogin: Date | null;\n\treadonly appVersion: string | null;\n\treadonly accountRoles: Record<string, boolean> | null;\n\treadonly roles: Record<string, boolean> | null;\n\treadonly notificationSettings: NotificationSettings | null;\n}\n\n/** User notification preferences. */\nexport interface NotificationSettings {\n\treadonly enabled: boolean;\n\treadonly continuousAlerts: boolean;\n\treadonly emailNotification: boolean;\n\treadonly smsNotification: boolean;\n\treadonly deviceNotification: boolean;\n}\n\n// ─── Account ─────────────────────────────────────────────────────────────────\n\n/** Account metadata. */\nexport interface Account {\n\treadonly accountId: string;\n\treadonly name: string | null;\n\treadonly type: string | null;\n\treadonly createdOn: Date | null;\n\treadonly exportVersion: number | null;\n}\n\n// ─── Events ──────────────────────────────────────────────────────────────────\n\n/** A device event (alarm, status change, alert). */\nexport interface DeviceEvent {\n\treadonly id: string;\n\treadonly eventType: string;\n\treadonly severity: number;\n\treadonly eventTime: Date;\n\treadonly deviceId: string;\n\treadonly channelId: string | null;\n\treadonly accountId: string;\n\treadonly valueBefore: string | null;\n\treadonly valueAfter: string | null;\n\treadonly groups: string[] | null;\n}\n\n/** Options for filtering events. */\nexport interface EventFilter {\n\t/** Filter by device serial. */\n\tdeviceId?: string;\n\t/** Filter by event type (e.g., \"Low Battery Alert\"). */\n\teventType?: string;\n\t/** Include events at or after this time. */\n\tstartTime?: Date;\n\t/** Include events at or before this time. */\n\tendTime?: Date;\n\t/** Maximum number of events to return (default 50). */\n\tlimit?: number;\n}\n\n// ─── Archives ────────────────────────────────────────────────────────────────\n\n/** A historical session archive. */\nexport interface Archive {\n\treadonly id: string;\n\treadonly start: Date | null;\n\treadonly end: Date | null;\n\treadonly count: number | null;\n\treadonly type: string | null;\n\treadonly label: string | null;\n\treadonly deviceLabel: string | null;\n\treadonly notes: string | null;\n\treadonly createdOn: Date | null;\n\treadonly public: boolean | null;\n\treadonly publicLink: string | null;\n\treadonly filename: string | null;\n\treadonly channels: ArchiveChannel[] | null;\n}\n\n/** A channel snapshot within an archive. */\nexport interface ArchiveChannel {\n\treadonly number: string | null;\n\treadonly label: string | null;\n\treadonly units: string | null;\n\treadonly value: number | null;\n\treadonly status: string | null;\n\treadonly enabled: boolean | null;\n\treadonly color: string | null;\n\treadonly type: string | null;\n\treadonly alarmHigh: Alarm | null;\n\treadonly alarmLow: Alarm | null;\n\treadonly minimum: MinMaxReading | null;\n\treadonly maximum: MinMaxReading | null;\n\treadonly recentReadings: TemperatureReading[];\n}\n\n/** A single temperature reading from an archive. */\nexport interface TemperatureReading {\n\treadonly value: number;\n\treadonly timestamp: Date;\n\treadonly units: string;\n}\n\n/** Options for listing archives. */\nexport interface ArchiveListOptions {\n\t/** Maximum number of archives to return (default 20). */\n\tlimit?: number;\n\t/** Cursor for pagination (archive document ID to start after). */\n\tstartAfter?: string;\n}\n\n// ─── Calibration ─────────────────────────────────────────────────────────────\n\n/** A factory calibration record. */\nexport interface CalibrationRecord {\n\treadonly calibrationId: string;\n\treadonly calibrationDate: Date | null;\n\treadonly deviceId: string;\n\treadonly sessionId: string | null;\n\treadonly performedBy: string | null;\n\treadonly manager: string | null;\n\treadonly referenceDetail: string | null;\n\treadonly statedAccuracy: string | null;\n\treadonly ambientTemperature: string | null;\n\treadonly ambientHumidity: string | null;\n\treadonly result: string | null;\n\treadonly lowPointAdjustments: CalibrationPoint[];\n\treadonly highPointReference: CalibrationPoint[];\n}\n\n/** A single calibration measurement point. */\nexport interface CalibrationPoint {\n\treadonly channel: number;\n\treadonly value: number;\n\treadonly units: string;\n\treadonly referenceValue: number;\n\treadonly deviation: number;\n\treadonly trimValue: number | null;\n\treadonly result: string;\n}\n\n// ─── Firmware ────────────────────────────────────────────────────────────────\n\n/** Firmware information for a device type. */\nexport interface FirmwareInfo {\n\treadonly name: string;\n\treadonly version: string;\n\treadonly location: string;\n\treadonly md5: string;\n}\n\n// ─── Content ─────────────────────────────────────────────────────────────────\n\n/** Cooking temperature guide. */\nexport interface TemperatureGuide {\n\treadonly categories: TemperatureCategory[];\n}\n\n/** A category in the temperature guide (e.g., Beef, Pork). */\nexport interface TemperatureCategory {\n\treadonly label: string;\n\treadonly icon: string;\n\treadonly pullWarning: string | null;\n\treadonly warning: string | null;\n}\n\n// ─── Search ──────────────────────────────────────────────────────────────────\n\n/** Search result from Typesense. */\nexport interface SearchResult {\n\treadonly hits: SearchHit[];\n\treadonly totalHits: number;\n\treadonly page: number;\n}\n\n/** A single search hit. */\nexport interface SearchHit {\n\treadonly id: string;\n\treadonly score: number;\n\treadonly document: Record<string, unknown>;\n}\n\n/** Options for search queries. */\nexport interface SearchOptions {\n\t/** Search collection: \"device\", \"accounts\", or \"users\". */\n\tcollection: \"device\" | \"accounts\" | \"users\";\n\t/** Page number (1-indexed). */\n\tpage?: number;\n\t/** Results per page. */\n\tpageSize?: number;\n}\n\n// ─── Sharing ─────────────────────────────────────────────────────────────────\n\n/** Result from a public sharing operation. */\nexport interface ShareResult {\n\treadonly success: boolean;\n\treadonly publicLink?: string;\n}\n\n// ─── Alarm Configuration ─────────────────────────────────────────────────────\n\n/** Options for configuring a single alarm threshold. */\nexport interface AlarmThresholdOptions {\n\t/** Alarm trigger value (temperature or humidity). */\n\tvalue: number;\n\t/** Units for the alarm value (e.g., \"F\", \"C\"). Defaults to the device's current units if omitted. */\n\tunits?: string;\n\t/** Whether this alarm threshold is enabled. */\n\tenabled?: boolean;\n\t/** Whether this alarm is muted (suppresses notifications). */\n\tmuted?: boolean;\n}\n\n/** Options for setting alarm thresholds on a device channel. At least one of `high` or `low` must be provided. */\nexport interface AlarmSetOptions {\n\t/** High alarm threshold configuration. */\n\thigh?: AlarmThresholdOptions;\n\t/** Low alarm threshold configuration. */\n\tlow?: AlarmThresholdOptions;\n}\n\n// ─── Billing & Storage ───────────────────────────────────────────────────────\n\n/** Total data storage usage for an account. */\nexport interface DataUsage {\n\treadonly totalBytes: number;\n\treadonly formattedSize: string;\n}\n\n/** Data storage usage for a single device. */\nexport interface DeviceDataUsage {\n\treadonly deviceId: string;\n\treadonly bytes: number;\n\treadonly formattedSize: string;\n}\n\n/** Billing plan details. */\nexport interface BillingPlan {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly description: string;\n\treadonly monthlyAmount: number;\n\treadonly deviceCount: number;\n\treadonly isDefault: boolean;\n}\n\n// ─── Account Invites ─────────────────────────────────────────────────────────\n\n/** A pending invitation to join an account. */\nexport interface AccountInvite {\n\treadonly id: string;\n\treadonly accountId: string;\n\treadonly email?: string;\n\treadonly status?: string;\n\treadonly createdAt?: string;\n}\n\n// ─── Actions (Callable Functions) ────────────────────────────────────────────\n\n/** Result from a callable function invocation. */\nexport interface ActionResult<T = unknown> {\n\treadonly success: boolean;\n\treadonly data: T | null;\n\treadonly error: string | null;\n}\n\n// ─── History ─────────────────────────────────────────────────────────────────\n\n/** A single historical temperature reading from BigQuery time-series data. */\nexport interface HistoricalReading {\n\treadonly value: number;\n\treadonly timestamp: string;\n\treadonly units: string;\n}\n\n/** Historical readings for a device retrieved from BigQuery. */\nexport interface DeviceHistory {\n\treadonly deviceId: string;\n\treadonly readings: HistoricalReading[];\n}\n\n// ─── Device Groups ───────────────────────────────────────────────────────────\n\n/** A device group organizing multiple devices together. */\nexport interface DeviceGroup {\n\treadonly id: string;\n\treadonly name: string;\n\treadonly devices: string[];\n}\n\n// ─── Filters ─────────────────────────────────────────────────────────────────\n\n/** Options for filtering devices. */\nexport interface DeviceFilter {\n\t/** Filter by device serial number(s). */\n\tserial?: string | string[];\n\t/** Filter by device type (e.g., \"node\", \"smoke\", \"signals\"). */\n\ttype?: string | string[];\n\t/** Filter by device label (exact match). */\n\tlabel?: string | string[];\n\t/** Filter by device status (e.g., \"online\", \"offline\"). */\n\tstatus?: string | string[];\n\t/** Only include devices seen within this many minutes. */\n\tactiveWithinMinutes?: number;\n}\n\n// ─── Device Health ───────────────────────────────────────────────────────────\n\n/** Overall health assessment for a device. */\nexport interface DeviceHealth {\n\treadonly overall: \"good\" | \"warning\" | \"critical\";\n\treadonly issues: DeviceHealthIssue[];\n}\n\n/** A single health issue detected on a device. */\nexport interface DeviceHealthIssue {\n\treadonly code:\n\t\t| \"stale_reading\"\n\t\t| \"low_battery\"\n\t\t| \"weak_wifi_signal\"\n\t\t| \"offline\"\n\t\t| \"firmware_outdated\";\n\treadonly severity: \"warning\" | \"critical\";\n\treadonly message: string;\n\treadonly detail?: string;\n}\n\n/** Error thrown when authentication fails. */\nexport class AuthError extends Error {\n\treadonly reason: string;\n\n\tconstructor(message: string, reason: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AuthError\";\n\t\tthis.reason = reason;\n\t}\n}\n\n/** Error thrown when a requested resource is not found. */\nexport class NotFoundError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"NotFoundError\";\n\t}\n}\n\n/** Error thrown on network/HTTP failures. */\nexport class NetworkError extends Error {\n\treadonly statusCode: number | null;\n\n\tconstructor(message: string, statusCode: number | null = null) {\n\t\tsuper(message);\n\t\tthis.name = \"NetworkError\";\n\t\tthis.statusCode = statusCode;\n\t}\n}\n"],"mappings":"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","names":[]}