UNPKG

benchling_typescript_sdk

Version:

Typescript SDK for Benchling API

117 lines (115 loc) 4.71 kB
import { connect } from "http2"; import { BenchlingClient } from "../BenchlingClient"; import { ContainerQuantity, MultipleContainersTransfer, Plate, SmallPlate } from "../types"; import { chunkArray } from "./chunkQueries"; /** * Given Plate[] - empty contents and then recreate the plate according to Plate[] * This is use to undo and restore previous versions of plates with potentially mixed contents in wells. */ export class ReCreatePlatesContents { private benchling: BenchlingClient; constructor(client: BenchlingClient) { this.benchling = client; } public async reCreatePlatesContents(originalPlates: SmallPlate[]): Promise<boolean> { try { // First, we need to empty the contents of the current plates let generator = this.benchling.plates.listSmallPlates({ ids: originalPlates.map((p) => p.id).join(","), }); for await (const currentPlates of generator) { currentPlates.forEach(async (plate) => { Object.keys(plate.wells).forEach(async (wellId) => { plate.wells[wellId].contents?.forEach(async (content) => { // delete whatever content is there currently. can only do one at a time :/ await this.benchling.containers.deleteContainerContent( // does this error if it doesn't work? must test plate.wells[wellId].id, content.entity.id ); }); }); }); } } catch (error: unknown) { console.error("\nUnable to DELETE container contents to recreate plates\n"); throw error; } // now all content is deleted // lets re-create the originalPlates by creating transfers let transfers: MultipleContainersTransfer[] = []; try { for (const plate of originalPlates) { for (const wellId in plate.wells) { let well = plate.wells[wellId]; if (!well.quantity || !well.quantity.value || !well.quantity.units) { continue; } if (well.quantity.units !== "mL" && well.quantity.units !== "uL") { throw Error( `Unsupported volume quantity unit in plate ${plate.barcode}:${wellId} - ${well.quantity.units} - must be 'uL' or 'mL'` ); } let quantityValue: number = well.quantity.value; let quanityUnits = well.quantity.units as "mL" | "uL"; let transferVolume: number = Math.floor(quantityValue || 0 / well.contents.length); let additionalVolume = quantityValue - transferVolume * well.contents.length; well.contents.forEach((content, i) => { let destinationContainerId: string = well.id; let sourceEntityId = content.entity.id; transfers.push({ destinationContainerId, sourceEntityId, transferQuantity: { units: quanityUnits, value: i === 0 ? transferVolume + additionalVolume : transferVolume, }, }); }); // add correct whole volume here - will use the other endpoint to update concentrations } } } catch (error: unknown) { console.error( "\nUnable to transfer entity volumes back into emptied plates in ReCreatePlatesContents\n" ); // Safely access the error message) throw error; } // now run the transferes try { await this.benchling.containers.waitForAllTransfers(transfers, 1000); } catch (error: unknown) { console.error("Error during entity volume transfers"); throw error; } try { for (const plate of originalPlates) { for (const wellId in plate.wells) { let well = plate.wells[wellId]; if (!well.quantity || !well.quantity.value || !well.quantity.units) { continue; } well.contents.forEach(async (content) => { if ( content.entity.id && content.concentration && content.concentration.value !== null && content.concentration.units !== null ) { // we need to update the concentration of the entity in the well await this.benchling.containers.patchContainerContent( well.id, content.entity.id, content.concentration ); } }); } } } catch (error: unknown) { console.error("Error updating concentrations during ReCreatePlatesContents"); throw error; // now the plates have the correct entities at a volume, but do not have concentrations } return true; // this should have worked!! } }