import { ResourceIndex } from "./interfaces"; import { TaggedResource, SpecialStatus, isTaggedResource, sanityCheck, TaggedWebcamFeed, TaggedFbosConfig, TaggedCrop, TaggedRegimen, TaggedImage, TaggedLog, TaggedTool, TaggedFarmEvent, TaggedSequence, TaggedPoint, TaggedSensor, TaggedPeripheral, TaggedWebAppConfig, TaggedFirmwareConfig, TaggedToolSlotPointer, TaggedPinBinding, TaggedDiagnosticDump, } from "./tagged_resources"; import { sortResourcesById, betterCompact, bail } from "../util"; import { error } from "farmbot-toastr"; import { joinKindAndId } from "./reducer"; import { assertUuid } from "./util"; const isSaved = (t: T) => t.specialStatus === SpecialStatus.SAVED; /** Generalized way to stamp out "finder" functions. * Pass in a `ResourceName` and it will add all the relevant checks. * WARNING: WILL THROW ERRORS IF RESOURCE NOT FOUND! */ const uuidFinder = (r: T["kind"]) => function findResource(i: ResourceIndex, u: string): T { assertUuid(r, u); const result = i.references[u]; if (result && isTaggedResource(result) && sanityCheck(result)) { return result as T; } else { error("Resource error"); throw new Error(`Tagged resource ${r} was not found or malformed: ` + JSON.stringify(result)); } }; export function findAll(index: ResourceIndex, kind: T["kind"]): T[] { const results: T[] = []; index.byKind[kind].map(function (uuid) { const item = index.references[uuid]; if (item && isTaggedResource(item) && (item.kind === kind)) { results.push(item as T); } }); return sortResourcesById(results) as T[]; } export let findTool = uuidFinder("Tool"); export let findSequence = uuidFinder("Sequence"); export let findRegimen = uuidFinder("Regimen"); export let findFarmEvent = uuidFinder("FarmEvent"); export let findPoints = uuidFinder("Point"); export const selectAllCrops = (i: ResourceIndex) => findAll(i, "Crop"); export const selectAllFarmEvents = (i: ResourceIndex) => findAll(i, "FarmEvent"); export const selectAllImages = (i: ResourceIndex) => findAll(i, "Image"); export const selectAllLogs = (i: ResourceIndex) => findAll(i, "Log"); export const selectAllPeripherals = (i: ResourceIndex) => findAll(i, "Peripheral"); export const selectAllPoints = (i: ResourceIndex) => findAll(i, "Point"); export const selectAllToolSlots = (i: ResourceIndex): TaggedToolSlotPointer[] => { return betterCompact(selectAllPoints(i) .map((x): TaggedToolSlotPointer | undefined => { const y = x.body; // Hack around TS taggedUnion issues (I think). return (y.pointer_type === "ToolSlot") ? { ...x, body: y } : undefined; })); }; export const selectAllDiagnosticDumps = (i: ResourceIndex) => findAll(i, "DiagnosticDump"); export const selectAllRegimens = (i: ResourceIndex) => findAll(i, "Regimen"); export const selectAllSensors = (i: ResourceIndex) => findAll(i, "Sensor"); export const selectAllPinBindings = (i: ResourceIndex) => findAll(i, "PinBinding"); export const selectAllSequences = (i: ResourceIndex) => findAll(i, "Sequence"); export const selectAllTools = (i: ResourceIndex) => findAll(i, "Tool"); export const selectAllSavedSensors = (input: ResourceIndex) => selectAllSensors(input).filter(isSaved); export const selectAllWebcamFeeds = (i: ResourceIndex) => findAll(i, "WebcamFeed"); export const getAllSavedPeripherals = (input: ResourceIndex) => selectAllPeripherals(input).filter(isSaved); export const getFbosConfig = (i: ResourceIndex): TaggedFbosConfig | undefined => findAll(i, "FbosConfig")[0]; export const getWebAppConfig = (i: ResourceIndex): TaggedWebAppConfig | undefined => findAll(i, "WebAppConfig")[0]; export const getFirmwareConfig = (i: ResourceIndex): TaggedFirmwareConfig | undefined => findAll(i, "FirmwareConfig")[0]; export const findByKindAndId = (i: ResourceIndex, kind: T["kind"], id: number | undefined): T => { const kni = joinKindAndId(kind, id); const uuid = i.byKindAndId[kni] || bail("Not found: " + kni); const resource = i.references[uuid] || bail("Not found uuid: " + uuid); if (resource.kind === kind) { return resource as T; // Why `as T`? } else { return bail("Impossible! " + uuid); } };