{"version":3,"sources":["../src/index.ts","../src/utils/common.ts","../src/esp/stream-transformers.ts","../src/esp/command.ts","../src/esp/command.sync.ts","../src/esp/command.spi-attach.ts","../src/esp/command.spi-set-params.ts","../src/esp/command.flash-begin.ts","../src/esp/command.flash-data.ts","../src/esp/command.read-reg.ts","../src/esp/command.mem-begin.ts","../src/esp/command.mem-data.ts","../src/esp/command.mem-end.ts","../src/esp/stub-flasher/stub_flasher_32.json","../src/esp/stub-flasher/stub_flasher_32s2.json","../src/esp/stub-flasher/stub_flasher_32s3.json","../src/esp/stub-flasher/stub_flasher_32c3.json","../src/esp/stub-flasher/stub_flasher_32c6.json","../src/esp/stub-flasher/stub_flasher_32h2.json","../src/esp/stub-flasher/stub_flasher_8266.json","../src/esp/serial-controller.ts","../src/image/bin-file-partition.ts","../src/image/image.ts","../src/utils/crc32.ts","../src/nvs/nvs-settings.ts","../src/nvs/nvs-entry.ts","../src/nvs/state-bitmap.ts","../src/nvs/nvs-page.ts","../src/nvs/nvs-partition.ts","../src/partition/partition-entry.ts","../src/partition/partition-types.ts","../src/partition/partition-table.ts"],"sourcesContent":["/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// --- Core Controller ---\nexport { SerialController } from \"./esp/serial-controller\";\nexport type { SerialConnection } from \"./esp/serial-controller\";\n\n// --- Image Creation ---\nexport { ESPImage } from \"./image/image\";\n\n// --- Partition Implementations ---\nexport { BinFilePartition } from \"./image/bin-file-partition\";\nexport { NVSPartition } from \"./nvs/nvs-partition\";\nexport { PartitionTable } from \"./partition/partition-table\";\n\n// --- Partition Interfaces and Types ---\nexport type { Partition } from \"./partition/partition\";\nexport type {\n  PartitionDefinition,\n  PartitionFlags,\n} from \"./partition/partition-types\";\nexport {\n  PartitionType,\n  AppPartitionSubType,\n  DataPartitionSubType,\n} from \"./partition/partition-types\";\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Returns a promise with a timeout for set milliseconds.\n * @param ms milliseconds to wait\n * @returns Promise that resolves after set ms.\n */\nexport function sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// Helper function to format a byte array into a hex string\nexport function toHex(bytes: Uint8Array): string {\n  return Array.from(bytes)\n    .map((b) => b.toString(16).padStart(2, \"0\"))\n    .join(\"\");\n}\n\n/* SLIP special character codes */\nexport enum SlipStreamBytes {\n  END = 0xc0, // Indicates end of packet\n  ESC = 0xdb, // Indicates byte stuffing\n  ESC_END = 0xdc, // ESC ESC_END means END data byte\n  ESC_ESC = 0xdd, // ESC ESC_ESC means ESC data byte\n}\n\n/**\n * Encode buffer using RFC 1055 (SLIP) standard\n * @param buffer\n * @returns Uint8Array buffer encoded.\n */\nexport function slipEncode(buffer: Uint8Array): Uint8Array {\n  const encoded = [SlipStreamBytes.END];\n  for (const byte of buffer) {\n    if (byte === SlipStreamBytes.END) {\n      encoded.push(SlipStreamBytes.ESC, SlipStreamBytes.ESC_END);\n    } else if (byte === SlipStreamBytes.ESC) {\n      encoded.push(SlipStreamBytes.ESC, SlipStreamBytes.ESC_ESC);\n    } else {\n      encoded.push(byte);\n    }\n  }\n  encoded.push(SlipStreamBytes.END);\n  return new Uint8Array(encoded);\n}\n\n/**\n * Decodes a Base64 string into a Uint8Array.\n * @param base64 The Base64 encoded string.\n * @returns The decoded Uint8Array.\n */\nexport function base64ToUint8Array(base64: string): Uint8Array {\n  const binaryString = atob(base64);\n  const len = binaryString.length;\n  const bytes = new Uint8Array(len);\n  for (let i = 0; i < len; i++) {\n    bytes[i] = binaryString.charCodeAt(i);\n  }\n  return bytes;\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SlipStreamBytes } from \"../utils/common\";\n\n/**\n * A generic string logging transformer.\n * It logs each chunk to the console and passes it through unmodified.\n */\nclass LoggingTransformer implements Transformer<string, string> {\n  /**\n   * Constructs a new LoggingTransformer.\n   * @param logPrefix A prefix string to prepend to each log message.\n   */\n  constructor(public logPrefix: string = \"STREAM LOG: \") {}\n  /**\n   * Logs the incoming chunk to the console with the configured prefix\n   * and then enqueues it to be passed to the next stage in the stream.\n   * @param chunk The string chunk to process.\n   * @param controller The TransformStreamDefaultController to enqueue the chunk.\n   */\n  transform(\n    chunk: string,\n    controller: TransformStreamDefaultController<string>,\n  ) {\n    console.log(this.logPrefix, chunk);\n    controller.enqueue(chunk);\n  }\n}\n\n/**\n * A generic Uint8Array logging transformer.\n * It logs each chunk to the console and passes it through unmodified.\n */\nclass Uint8LoggingTransformer implements Transformer<Uint8Array, Uint8Array> {\n  /**\n   * Constructs a new Uint8LoggingTransformer.\n   * @param logPrefix A prefix string to prepend to each log message.\n   */\n  constructor(public logPrefix: string = \"UINT8 STREAM LOG: \") {}\n  /**\n   * Logs the incoming chunk to the console with the configured prefix\n   * and then enqueues it to be passed to the next stage in the stream.\n   * @param chunk The Uint8Array chunk to process.\n   * @param controller The TransformStreamDefaultController to enqueue the chunk.\n   */\n  transform(\n    chunk: Uint8Array,\n    controller: TransformStreamDefaultController<Uint8Array>,\n  ) {\n    console.log(this.logPrefix, chunk);\n    controller.enqueue(chunk);\n  }\n}\n\n/**\n * A transformer that buffers incoming string chunks and splits them into lines based on `\\r\\n` separators.\n * It ensures that only complete lines are enqueued. Any partial line at the end of a chunk is buffered\n * and prepended to the next chunk.\n */\nclass LineBreakTransformer implements Transformer<string, string> {\n  buffer: string | undefined = \"\";\n  transform(\n    chunk: string,\n    controller: TransformStreamDefaultController<string>,\n  ) {\n    this.buffer += chunk;\n    const lines = this.buffer?.split(\"\\r\\n\");\n    this.buffer = lines?.pop();\n    lines?.forEach((line) => controller.enqueue(line));\n  }\n}\n\n/**\n * Implements the SLIP (Serial Line Internet Protocol) encoding and decoding logic.\n * This transformer can be configured to operate in either encoding or decoding mode.\n */\nexport class SlipStreamTransformer\n  implements Transformer<Uint8Array, Uint8Array>\n{\n  private decoding = false; // Flag to indicate if the initial END byte for a packet has been received in decoding mode.\n  private escape = false; // Flag to indicate if the current byte is an escape character in decoding mode.\n  private frame: number[] = []; // Buffer to accumulate bytes for the current frame.\n\n  /**\n   * Constructs a new SlipStreamTransformer.\n   * @param mode Specifies whether the transformer should operate in \"encoding\" or \"decoding\" mode.\n   */\n  constructor(private mode: \"encoding\" | \"decoding\") {\n    if (this.mode === \"encoding\") {\n      this.decoding = false; // In encoding mode, 'decoding' state is not used.\n    }\n  }\n\n  transform(\n    chunk: Uint8Array,\n    controller: TransformStreamDefaultController<Uint8Array>,\n  ) {\n    if (this.mode === \"decoding\") {\n      for (const byte of chunk) {\n        // State machine for decoding SLIP frames\n        if (this.decoding) {\n          // Currently inside a frame\n          if (this.escape) {\n            // Previous byte was ESC\n            if (byte === SlipStreamBytes.ESC_END) {\n              this.frame.push(SlipStreamBytes.END);\n            } else if (byte === SlipStreamBytes.ESC_ESC) {\n              this.frame.push(SlipStreamBytes.ESC);\n            } else {\n              // This case should ideally not happen in a valid SLIP stream,\n              // but we'll add the byte as is to be robust.\n              this.frame.push(byte);\n            }\n            this.escape = false;\n          } else if (byte === SlipStreamBytes.ESC) {\n            // Start of an escape sequence\n            this.escape = true;\n          } else if (byte === SlipStreamBytes.END) {\n            // End of the current frame\n            if (this.frame.length > 0) {\n              controller.enqueue(new Uint8Array(this.frame));\n            }\n            this.frame = []; // Reset frame buffer for the next packet\n            // this.decoding remains true as we might receive multiple packets\n          } else {\n            // Regular data byte\n            this.frame.push(byte);\n          }\n        } else if (byte === SlipStreamBytes.END) {\n          // Start of a new frame (or end of a previous one, signaling start of a new one)\n          this.decoding = true;\n          this.frame = []; // Clear any previous partial frame data\n          this.escape = false;\n        }\n        // Bytes received before the first END in decoding mode are ignored.\n      }\n    } else {\n      // Encoding mode: Escapes special SLIP bytes (END, ESC) in the input chunk\n      // and accumulates them in an internal buffer. The actual packet framing\n      // with END bytes is handled in the flush method.\n      for (const byte of chunk) {\n        if (byte === SlipStreamBytes.END) {\n          this.frame.push(SlipStreamBytes.ESC, SlipStreamBytes.ESC_END);\n        } else if (byte === SlipStreamBytes.ESC) {\n          this.frame.push(SlipStreamBytes.ESC, SlipStreamBytes.ESC_ESC);\n        } else {\n          this.frame.push(byte);\n        }\n      }\n    }\n  }\n\n  flush(controller: TransformStreamDefaultController<Uint8Array>) {\n    if (this.mode === \"encoding\") {\n      // For encoding mode, wraps the accumulated frame buffer with SLIP END bytes\n      // to form a complete packet, then enqueues it.\n      // Only enqueue if there's data to send to avoid empty packets.\n      if (this.frame.length > 0) {\n        const finalPacket = new Uint8Array([\n          SlipStreamBytes.END,\n          ...this.frame,\n          SlipStreamBytes.END,\n        ]);\n        controller.enqueue(finalPacket);\n        this.frame = []; // Clear the frame buffer after flushing\n      }\n    }\n    // The decoder does not need any specific flush logic, as partial frames\n    // are handled by the transform method. Any remaining data in `this.frame`\n    // when the stream closes is considered an incomplete packet and is discarded.\n  }\n}\n\n/**\n * Creates a TransformStream that logs string chunks to the console.\n * @returns A new TransformStream instance with a LoggingTransformer.\n */\nexport function createLoggingTransformer() {\n  return new TransformStream<string, string>(new LoggingTransformer());\n}\n\n/**\n * Creates a TransformStream that logs Uint8Array chunks to the console.\n * @returns A new TransformStream instance with a Uint8LoggingTransformer.\n */\nexport function createUint8LoggingTransformer() {\n  return new TransformStream<Uint8Array, Uint8Array>(\n    new Uint8LoggingTransformer(),\n  );\n}\n\n/**\n * Creates a TransformStream that returns full lines only.\n * Chunks are saved to buffer until `\\r\\n` is send.\n * @returns TransformStream\n */\nexport function createLineBreakTransformer() {\n  return new TransformStream<string, string>(new LineBreakTransformer());\n}\n\n/**\n * TranformStream that encodes data according to the RFC 1055 (SLIP) standard.\n * It takes a stream of Uint8Array chunks and outputs a stream of Uint8Array chunks\n * where each output chunk represents a SLIP-encoded packet.\n * @example\n * const rawDataStream = getSomeUint8ArrayStream();\n * const slipEncodedStream = rawDataStream.pipeThrough(new SlipStreamEncoder());\n */\nexport class SlipStreamEncoder extends TransformStream<Uint8Array, Uint8Array> {\n  /**\n   * Constructs a new SlipStreamEncoder.\n   * This sets up the underlying SlipStreamTransformer in \"encoding\" mode.\n   */\n  constructor() {\n    super(new SlipStreamTransformer(\"encoding\"));\n  }\n}\n\n/**\n * TranformStream that decodes data according to the RFC 1055 (SLIP) standard.\n * It takes a stream of Uint8Array chunks (potentially partial SLIP packets) and\n * outputs a stream of Uint8Array chunks where each output chunk represents a\n * decoded SLIP frame (the original data without SLIP framing and escaping).\n * @example\n * const slipEncodedStream = getSomeSlipEncodedStream();\n * const decodedDataStream = slipEncodedStream.pipeThrough(new SlipStreamDecoder());\n */\nexport class SlipStreamDecoder extends TransformStream<Uint8Array, Uint8Array> {\n  /**\n   * Constructs a new SlipStreamDecoder.\n   * This sets up the underlying SlipStreamTransformer in \"decoding\" mode.\n   */\n  constructor() {\n    super(new SlipStreamTransformer(\"decoding\"));\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { slipEncode } from \"../utils/common\";\n\nexport enum EspPacketDirection {\n  REQUEST = 0x00,\n  RESPONSE = 0x01,\n}\n\nexport enum EspCommand {\n  // Commands supported by ROM and Stub loaders\n  FLASH_BEGIN = 0x02,\n  FLASH_DATA = 0x03,\n  FLASH_END = 0x04,\n  MEM_BEGIN = 0x05,\n  MEM_END = 0x06,\n  MEM_DATA = 0x07,\n  SYNC = 0x08,\n  WRITE_REG = 0x09,\n  READ_REG = 0x0a,\n  SPI_SET_PARAMS = 0x0b,\n  SPI_ATTACH = 0x0d,\n  CHANGE_BAUDRATE = 0x0f,\n  FLASH_DEFL_BEGIN = 0x10,\n  FLASH_DEFL_DATA = 0x11,\n  FLASH_DEFL_END = 0x12,\n  SPI_FLASH_MD5 = 0x13,\n\n  // Stub loader only commands\n  ERASE_FLASH = 0xd0,\n  ERASE_REGION = 0xd1,\n  READ_FLASH = 0xd2,\n  RUN_USER_CODE = 0xd3,\n}\n\nexport class EspCommandPacket {\n  private packetHeader: Uint8Array = new Uint8Array(8);\n  private packetData: Uint8Array = new Uint8Array(0);\n\n  set direction(direction: EspPacketDirection) {\n    new DataView(this.packetHeader.buffer, 0, 1).setUint8(0, direction);\n  }\n\n  get direction(): EspPacketDirection {\n    return new DataView(this.packetHeader.buffer, 0, 1).getUint8(0);\n  }\n\n  set command(command: EspCommand) {\n    new DataView(this.packetHeader.buffer, 1, 1).setUint8(0, command);\n  }\n\n  get command(): EspCommand {\n    return new DataView(this.packetHeader.buffer, 1, 1).getUint8(0);\n  }\n\n  set size(size: number) {\n    new DataView(this.packetHeader.buffer, 2, 2).setUint16(0, size, true);\n  }\n\n  get size(): number {\n    return new DataView(this.packetHeader.buffer, 2, 2).getUint16(0, true);\n  }\n\n  set checksum(checksum: number) {\n    new DataView(this.packetHeader.buffer, 4, 4).setUint32(0, checksum, true);\n  }\n\n  get checksum(): number {\n    return new DataView(this.packetHeader.buffer, 4, 4).getUint32(0, true);\n  }\n\n  set value(value: number) {\n    new DataView(this.packetHeader.buffer, 4, 4).setUint32(0, value, true);\n  }\n\n  get value(): number {\n    return new DataView(this.packetHeader.buffer, 4, 4).getUint32(0, true);\n  }\n\n  get status(): number {\n    return new DataView(this.packetData.buffer, 0, 1).getUint8(0);\n  }\n\n  get error(): number {\n    return new DataView(this.packetData.buffer, 1, 1).getUint8(0);\n  }\n\n  generateChecksum(data: Uint8Array): number {\n    let cs = 0xef;\n    for (const byte of data) {\n      cs ^= byte;\n    }\n    return cs;\n  }\n\n  set data(packetData: Uint8Array) {\n    this.size = packetData.length;\n    this.packetData = packetData;\n  }\n\n  get data(): Uint8Array {\n    return this.packetData;\n  }\n\n  parseResponse(responsePacket: Uint8Array) {\n    const responseDataView = new DataView(responsePacket.buffer);\n    this.direction = responseDataView.getUint8(0) as EspPacketDirection;\n    this.command = responseDataView.getUint8(1) as EspCommand;\n    this.size = responseDataView.getUint16(2, true);\n    this.value = responseDataView.getUint32(4, true);\n    this.packetData = responsePacket.slice(8);\n\n    if (this.status === 1) {\n      console.log(this.getErrorMessage(this.error));\n    }\n  }\n\n  getErrorMessage(error: number): string {\n    switch (error) {\n      case 0x05:\n        return \"Status Error: Received message is invalid. (parameters or length field is invalid)\";\n      case 0x06:\n        return \"Failed to act on received message\";\n      case 0x07:\n        return \"Invalid CRC in message\";\n      case 0x08:\n        return \"flash write error - after writing a block of data to flash, the ROM loader reads the value back and the 8-bit CRC is compared to the data read from flash. If they don't match, this error is returned.\";\n      case 0x09:\n        return \"flash read error - SPI read failed\";\n      case 0x0a:\n        return \"flash read length error - SPI read request length is too long\";\n      case 0x0b:\n        return \"Deflate error (compressed uploads only)\";\n      default:\n        return \"No error status for response\";\n    }\n  }\n\n  getPacketData(): Uint8Array {\n    const header = new Uint8Array(8);\n    const view = new DataView(header.buffer);\n    view.setUint8(0, this.direction);\n    view.setUint8(1, this.command);\n    view.setUint16(2, this.data.length, true);\n    view.setUint32(4, this.checksum, true);\n    return new Uint8Array([...header, ...this.data]);\n  }\n\n  getSlipStreamEncodedPacketData(): Uint8Array {\n    return slipEncode(this.getPacketData());\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandSync extends EspCommandPacket {\n  constructor() {\n    super();\n\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.SYNC;\n    this.data = new Uint8Array([\n      0x07, 0x07, 0x12, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n      0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n      0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n    ]);\n    this.checksum = 0;\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandSpiAttach extends EspCommandPacket {\n  private spiAttachData = new ArrayBuffer(8);\n  private view1 = new DataView(this.spiAttachData, 0, 4);\n  private view2 = new DataView(this.spiAttachData, 4, 4);\n\n  constructor() {\n    super();\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.SPI_ATTACH;\n\n    this.view1.setUint32(0, 0, true);\n    this.view2.setUint32(0, 0, true);\n    this.data = new Uint8Array(this.spiAttachData);\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandSpiSetParams extends EspCommandPacket {\n  private paramsData = new ArrayBuffer(24);\n  private id = new DataView(this.paramsData, 0, 4);\n  private totalSize = new DataView(this.paramsData, 4, 4);\n  private blockSize = new DataView(this.paramsData, 8, 4);\n  private sectorSize = new DataView(this.paramsData, 12, 4);\n  private pageSize = new DataView(this.paramsData, 16, 4);\n  private statusMask = new DataView(this.paramsData, 20, 4);\n\n  constructor() {\n    super();\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.SPI_SET_PARAMS;\n    this.id.setUint32(0, 0, true);\n    this.totalSize.setUint32(0, 4 * 1024 * 1024, true);\n    this.blockSize.setUint32(0, 0x10000, true);\n    this.sectorSize.setUint32(0, 0x1000, true);\n    this.pageSize.setUint32(0, 0x100, true);\n    this.statusMask.setUint32(0, 0xffffffff, true);\n    this.data = new Uint8Array(this.paramsData);\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandFlashBegin extends EspCommandPacket {\n  private flashBeginData = new ArrayBuffer(16);\n  private eraseSizeView = new DataView(this.flashBeginData, 0, 4);\n  private numDataPacketsView = new DataView(this.flashBeginData, 4, 4);\n  private dataSizeView = new DataView(this.flashBeginData, 8, 4);\n  private offsetView = new DataView(this.flashBeginData, 12, 4);\n\n  constructor(\n    image: Uint8Array,\n    offset: number,\n    packetSize: number,\n    numPackets: number,\n  ) {\n    super();\n\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.FLASH_BEGIN;\n    this.eraseSizeView.setUint32(0, image.length, true);\n    this.numDataPacketsView.setUint32(0, numPackets, true);\n    this.dataSizeView.setUint32(0, packetSize, true);\n    this.offsetView.setUint32(0, offset, true);\n    this.data = new Uint8Array(this.flashBeginData);\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandFlashData extends EspCommandPacket {\n  constructor(image: Uint8Array, sequenceNumber: number, blockSize: number) {\n    super();\n\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.FLASH_DATA;\n\n    const flashDownloadData = new Uint8Array(16 + blockSize);\n    const blockSizeView = new DataView(flashDownloadData.buffer, 0, 4);\n    const sequenceView = new DataView(flashDownloadData.buffer, 4, 4);\n    const paddingView = new DataView(flashDownloadData.buffer, 8, 8);\n\n    blockSizeView.setUint32(0, blockSize, true);\n    sequenceView.setUint32(0, sequenceNumber, true);\n\n    paddingView.setUint32(0, 0, true);\n    paddingView.setUint32(4, 0, true);\n\n    const block = image.slice(\n      sequenceNumber * blockSize,\n      sequenceNumber * blockSize + blockSize,\n    );\n\n    const blockData = new Uint8Array(blockSize);\n    blockData.fill(0xff);\n    blockData.set(block, 0);\n\n    flashDownloadData.set(blockData, 16);\n    this.data = flashDownloadData;\n    this.checksum = this.generateChecksum(blockData);\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandReadReg extends EspCommandPacket {\n  private readRegData = new ArrayBuffer(4);\n\n  constructor(address: number) {\n    super();\n\n    this.command = EspCommand.READ_REG;\n    this.direction = EspPacketDirection.REQUEST;\n    new DataView(this.readRegData).setUint32(0, address, true);\n    this.data = new Uint8Array(this.readRegData);\n  }\n}\n","import { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandMemBegin extends EspCommandPacket {\n  constructor(\n    public totalSize: number,\n    public numPackets: number,\n    public packetSize: number,\n    public offset: number,\n  ) {\n    super();\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.MEM_BEGIN;\n    this.checksum = 0; // Not used for this command\n\n    const dataPayload = new Uint8Array(16);\n    const view = new DataView(dataPayload.buffer);\n    view.setUint32(0, this.totalSize, true);\n    view.setUint32(4, this.numPackets, true);\n    view.setUint32(8, this.packetSize, true);\n    view.setUint32(12, this.offset, true);\n\n    this.data = dataPayload;\n  }\n}\n","import { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandMemData extends EspCommandPacket {\n  constructor(\n    public binary: Uint8Array,\n    public sequence: number,\n    public packetSize: number,\n  ) {\n    super();\n\n    const chunk = binary.slice(\n      sequence * packetSize,\n      (sequence + 1) * packetSize,\n    );\n\n    const header = new Uint8Array(16);\n    const view = new DataView(header.buffer);\n    view.setUint32(0, chunk.length, true); // Data size\n    view.setUint32(4, sequence, true); // Sequence number\n    view.setUint32(8, 0, true); // Zero\n    view.setUint32(12, 0, true); // Zero\n\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.MEM_DATA;\n    this.data = new Uint8Array([...header, ...chunk]);\n    this.checksum = this.generateChecksum(chunk);\n  }\n}\n","import { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\n\nexport class EspCommandMemEnd extends EspCommandPacket {\n  constructor(\n    public executeFlag: number,\n    public entryPoint: number,\n  ) {\n    super();\n    this.direction = EspPacketDirection.REQUEST;\n    this.command = EspCommand.MEM_END;\n    this.checksum = 0; // Not used\n\n    const dataPayload = new Uint8Array(8);\n    const view = new DataView(dataPayload.buffer);\n    view.setUint32(0, this.executeFlag, true);\n    view.setUint32(4, this.entryPoint, true);\n\n    this.data = dataPayload;\n  }\n}\n","{\n    \"entry\": 1074521580,\n    \"text\": \"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\",\n    \"text_start\": 1074520064,\n    \"data\": \"DMD8P+znC0B/6AtAZ+0LQAbpC0Cf6AtABukLQGXpC0CC6gtA9OoLQJ3qC0CV5wtAGuoLQHTqC0CI6QtAGOsLQLDpC0AY6wtAbegLQMroC0AG6QtAZekLQIXoC0DI6wtAKe0LQLjmC0BL7QtAuOYLQLjmC0C45gtAuOYLQLjmC0C45gtAuOYLQLjmC0Bv6wtAuOYLQEnsC0Ap7QtA\",\n    \"data_start\": 1073605544,\n    \"bss_start\": 1073528832\n}","{\n    \"entry\": 1073907716,\n    \"text\": \"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\",\n    \"text_start\": 1073905664,\n    \"data\": \"WAD9P0uLAkDdiwJA8pACQGaMAkD+iwJAZowCQMWMAkDejQJAUY4CQPmNAkDVigJAd40CQNCNAkDojAJAdI4CQBCNAkB0jgJAy4sCQCqMAkBmjAJAxYwCQOOLAkAXiwJAN48CQKqQAkDqiQJA0ZACQOqJAkDqiQJA6okCQOqJAkDqiQJA6okCQOqJAkDqiQJA1I4CQOqJAkDJjwJAqpACQA==\",\n    \"data_start\": 1073622012,\n    \"bss_start\": 1073545216\n}","{\n    \"entry\": 1077381760,\n    \"text\": \"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\",\n    \"text_start\": 1077379072,\n    \"data\": \"XADKP16ON0AzjzdAR5Q3QL2PN0BTjzdAvY83QB2QN0A6kTdArJE3QFWRN0DpjTdA0JA3QCyRN0BAkDdA0JE3QGiQN0DQkTdAIY83QH6PN0C9jzdAHZA3QDmPN0AqjjdAkJI3QA2UN0AAjTdALZQ3QACNN0AAjTdAAI03QACNN0AAjTdAAI03QACNN0AAjTdAKpI3QACNN0AlkzdADZQ3QAQInwAAAAAAAAAYAQQIBQAAAAAAAAAIAQQIBgAAAAAAAAAAAQQIIQAAAAAAIAAAEQQI3AAAAAAAIAAAEQQIDAAAAAAAIAAAAQQIEgAAAAAAIAAAESAoDAAQAQAA\",\n    \"data_start\": 1070279676,\n    \"bss_start\": 1070202880\n}","{\n    \"entry\": 1077413584,\n    \"text\": \"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\",\n    \"text_start\": 1077411840,\n    \"data\": \"GEDIP8AKOEAQCzhAaAs4QDYMOECiDDhAUAw4QHIJOEDyCzhAMgw4QHwLOEAiCThAsAs4QCIJOECaCjhA4Ao4QBALOEBoCzhArAo4QNYJOEAgCjhAqAo4QPoOOEAQCzhAug04QLIOOEBiCDhA2g44QGIIOEBiCDhAYgg4QGIIOEBiCDhAYgg4QGIIOEBiCDhAVg04QGIIOEDYDThAsg44QA==\",\n    \"data_start\": 1070164916,\n    \"bss_start\": 1070088192\n}","{\n    \"entry\": 1082132164,\n    \"text\": \"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\",\n    \"text_start\": 1082130432,\n    \"data\": \"FACEQHIKgEDCCoBAGguAQOgLgEBUDIBAAgyAQD4JgECkC4BA5AuAQC4LgEDuCIBAYguAQO4IgEBMCoBAkgqAQMIKgEAaC4BAXgqAQKIJgEDSCYBAWgqAQKwOgEDCCoBAbA2AQGQOgEAuCIBAjA6AQC4IgEAuCIBALgiAQC4IgEAuCIBALgiAQC4IgEAuCIBACA2AQC4IgECKDYBAZA6AQA==\",\n    \"data_start\": 1082469296,\n    \"bss_start\": 1082392576\n}","{\n    \"entry\": 1082132164,\n    \"text\": \"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\",\n    \"text_start\": 1082130432,\n    \"data\": \"FACDQHIKgEDCCoBAGguAQOgLgEBUDIBAAgyAQD4JgECkC4BA5AuAQC4LgEDuCIBAYguAQO4IgEBMCoBAkgqAQMIKgEAaC4BAXgqAQKIJgEDSCYBAWgqAQKwOgEDCCoBAbA2AQGQOgEAuCIBAjA6AQC4IgEAuCIBALgiAQC4IgEAuCIBALgiAQC4IgEAuCIBACA2AQC4IgECKDYBAZA6AQA==\",\n    \"data_start\": 1082403760,\n    \"bss_start\": 1082327040\n}","{\n    \"entry\": 1074843652,\n    \"text\": \"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\",\n    \"text_start\": 1074843648,\n    \"data\": \"CIH+PwUFBAACAwcAAwMLANTXEEAL2BBAOdgQQNbYEECF5xBAOtkQQJDZEEDc2RBAhecQQKLaEEAf2xBA4NsQQIXnEECF5xBAeNwQQIXnEEBV3xBAHOAQQFfgEECF5xBAhecQQPPgEECF5xBA2+EQQIHiEEDA4xBAf+QQQFDlEECF5xBAhecQQIXnEECF5xBAfuYQQIXnEEB05xBAsN0QQKnYEEDC5RBAydoQQBvaEECF5xBACOcQQE/nEECF5xBAhecQQIXnEECF5xBAhecQQIXnEECF5xBAhecQQELaEEB/2hBA2uUQQAEAAAACAAAAAwAAAAQAAAAFAAAABwAAAAkAAAANAAAAEQAAABkAAAAhAAAAMQAAAEEAAABhAAAAgQAAAMEAAAABAQAAgQEAAAECAAABAwAAAQQAAAEGAAABCAAAAQwAAAEQAAABGAAAASAAAAEwAAABQAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAAAAAAAAAAAAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAANAAAADwAAABEAAAATAAAAFwAAABsAAAAfAAAAIwAAACsAAAAzAAAAOwAAAEMAAABTAAAAYwAAAHMAAACDAAAAowAAAMMAAADjAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAACAAAAAgAAAAMAAAADAAAAAwAAAAMAAAAEAAAABAAAAAQAAAAEAAAABQAAAAUAAAAFAAAABQAAAAAAAAAAAAAAAAAAABAREgAIBwkGCgULBAwDDQIOAQ8AAQEAAAEAAAAEAAAA\",\n    \"data_start\": 1073720488,\n    \"bss_start\": 1073643776\n}","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n  createLineBreakTransformer,\n  SlipStreamDecoder,\n} from \"./stream-transformers\";\nimport { sleep, toHex, base64ToUint8Array } from \"../utils/common\";\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\nimport { ESPImage } from \"../image/image\";\nimport { Partition } from \"../partition/partition\";\n\n// Import all necessary command classes\nimport { EspCommandSync } from \"./command.sync\";\nimport { EspCommandSpiAttach } from \"./command.spi-attach\";\nimport { EspCommandSpiSetParams } from \"./command.spi-set-params\";\nimport { EspCommandFlashBegin } from \"./command.flash-begin\";\nimport { EspCommandFlashData } from \"./command.flash-data\";\nimport { EspCommandReadReg } from \"./command.read-reg\";\nimport { EspCommandMemBegin } from \"./command.mem-begin\";\nimport { EspCommandMemData } from \"./command.mem-data\";\nimport { EspCommandMemEnd } from \"./command.mem-end\";\n\nimport stub32 from \"./stub-flasher/stub_flasher_32.json\";\nimport stub32s2 from \"./stub-flasher/stub_flasher_32s2.json\";\nimport stub32s3 from \"./stub-flasher/stub_flasher_32s3.json\";\nimport stub32c3 from \"./stub-flasher/stub_flasher_32c3.json\";\nimport stub32c6 from \"./stub-flasher/stub_flasher_32c6.json\";\nimport stub32h2 from \"./stub-flasher/stub_flasher_32h2.json\";\nimport stub8266 from \"./stub-flasher/stub_flasher_8266.json\";\n\n/**\n * Default serial options when connecting to an ESP32.\n */\nconst DEFAULT_ESP32_SERIAL_OPTIONS: SerialOptions = {\n  baudRate: 115200,\n  dataBits: 8,\n  stopBits: 1,\n  bufferSize: 255,\n  parity: \"none\",\n  flowControl: \"none\",\n};\n\n/**\n * Known chip families and their magic values.\n */\nexport enum ChipFamily {\n  ESP32 = 0x00f01d83,\n  ESP32S2 = 0x000007c6,\n  ESP32S3 = 0x9,\n  ESP32C3 = 0x6921506f,\n  ESP32C6 = 0x2ce0806f,\n  ESP32H2 = 0xca02c06f,\n  ESP8266 = 0xfff0c101,\n  UNKNOWN = 0xffffffff,\n}\n\n/**\n * Interface representing the structure of a flasher stub JSON file.\n */\nexport interface Stub {\n  entry: number;\n  text_start: number;\n  text: string; // Base64 encoded\n  data_start: number;\n  data: string; // Base64 encoded\n}\n\n/**\n * Interface defining the properties of a serial connection.\n */\nexport interface SerialConnection {\n  /** The underlying SerialPort object. Undefined if no port is selected. */\n  port: SerialPort | undefined;\n  /** Indicates if the serial port is currently open and connected. */\n  connected: boolean;\n  /** Indicates if the connection has been synchronized with the device. */\n  synced: boolean;\n  /** The detected chip family. Null if not yet detected. */\n  chip: ChipFamily | null;\n  /** The readable stream for receiving data from the serial port. Null if not connected. */\n  readable: ReadableStream<Uint8Array> | null;\n  /** The writable stream for sending data to the serial port. Null if not connected. */\n  writable: WritableStream<Uint8Array> | null;\n  /** An AbortController to signal termination of stream operations. Undefined if not connected. */\n  abortStreamController: AbortController | undefined;\n  /** A readable stream that contains the slipstream decoded responses from the esp. */\n  commandResponseStream: ReadableStream<Uint8Array> | undefined;\n}\n\nconst STUB_FILES: Partial<Record<ChipFamily, Stub>> = {\n  [ChipFamily.ESP32]: stub32 as unknown as Stub,\n  [ChipFamily.ESP32S2]: stub32s2 as unknown as Stub,\n  [ChipFamily.ESP32S3]: stub32s3 as unknown as Stub,\n  [ChipFamily.ESP32C3]: stub32c3 as unknown as Stub,\n  [ChipFamily.ESP32C6]: stub32c6 as unknown as Stub,\n  [ChipFamily.ESP32H2]: stub32h2 as unknown as Stub,\n  [ChipFamily.ESP8266]: stub8266 as unknown as Stub,\n};\n\nexport class SerialController extends EventTarget {\n  public connection: SerialConnection;\n\n  constructor() {\n    super();\n    this.connection = this.createSerialConnection();\n  }\n\n  private createSerialConnection(): SerialConnection {\n    return {\n      port: undefined,\n      connected: false,\n      synced: false,\n      chip: null,\n      readable: null,\n      writable: null,\n      abortStreamController: undefined,\n      commandResponseStream: undefined,\n    };\n  }\n\n  public async requestPort(): Promise<void> {\n    this.connection.port = await navigator.serial.requestPort();\n    this.connection.synced = false;\n    this.connection.chip = null;\n  }\n\n  public createLogStreamReader(): () => AsyncGenerator<\n    string | undefined,\n    void,\n    unknown\n  > {\n    if (\n      !this.connection.connected ||\n      !this.connection.readable ||\n      !this.connection.abortStreamController\n    )\n      return async function* logStream() { };\n\n    const streamPipeOptions = {\n      signal: this.connection.abortStreamController.signal,\n      preventCancel: false,\n      preventClose: false,\n      preventAbort: false,\n    };\n\n    const [newReadable, logReadable] = this.connection.readable.tee();\n    this.connection.readable = newReadable;\n\n    const reader = logReadable\n      .pipeThrough(new TextDecoderStream() as unknown as ReadableWritablePair<string, Uint8Array>, streamPipeOptions)\n      .pipeThrough(createLineBreakTransformer(), streamPipeOptions)\n      .getReader();\n\n    const connection = this.connection;\n    return async function* logStream() {\n      try {\n        while (connection.connected) {\n          const result = await reader?.read();\n          if (result?.done) return;\n          yield result?.value;\n        }\n      } finally {\n        reader?.releaseLock();\n      }\n    };\n  }\n\n  public async openPort(\n    options: SerialOptions = DEFAULT_ESP32_SERIAL_OPTIONS,\n  ): Promise<void> {\n    if (!this.connection.port) return;\n    await this.connection?.port.open(options);\n\n    if (!this.connection.port?.readable) return;\n\n    this.connection.abortStreamController = new AbortController();\n    const [commandTee, logTee] = this.connection.port.readable.tee();\n\n    this.connection.connected = true;\n    this.connection.readable = logTee;\n    this.connection.writable = this.connection.port.writable;\n    this.connection.commandResponseStream = commandTee.pipeThrough(\n      new SlipStreamDecoder(),\n      { signal: this.connection.abortStreamController.signal },\n    );\n  }\n\n  public async disconnect(): Promise<void> {\n    if (!this.connection.connected || !this.connection.port) {\n      return;\n    }\n\n    // Abort any ongoing stream operations\n    this.connection.abortStreamController?.abort();\n\n    try {\n      await this.connection.port.close();\n    } catch (error) {\n      // The port might already be closed or disconnected by the device.\n      console.error(\"Failed to close the serial port:\", error);\n    }\n\n    // Reset the connection state, but keep the port reference\n    const port = this.connection.port;\n    this.connection = this.createSerialConnection();\n    this.connection.port = port;\n  }\n\n  public async sendResetPulse(): Promise<void> {\n    if (!this.connection.port) return;\n    this.connection.port.setSignals({\n      dataTerminalReady: false,\n      requestToSend: true,\n    });\n    await sleep(100);\n    this.connection.port.setSignals({\n      dataTerminalReady: true,\n      requestToSend: false,\n    });\n    await sleep(100);\n  }\n\n  public async writeToConnection(data: Uint8Array) {\n    if (this.connection.writable) {\n      const writer = this.connection.writable.getWriter();\n      await writer.write(data);\n      writer.releaseLock();\n    }\n  }\n\n  public async sync(): Promise<boolean> {\n    await this.sendResetPulse();\n    const maxAttempts = 10;\n    const timeoutPerAttempt = 500; // ms\n\n    const syncCommand = new EspCommandSync();\n\n    for (let i = 0; i < maxAttempts; i++) {\n      this.dispatchEvent(\n        new CustomEvent(\"sync-progress\", {\n          detail: { progress: (i / maxAttempts) * 100 },\n        }),\n      );\n      console.log(`Sync attempt ${i + 1} of ${maxAttempts}`);\n      await this.writeToConnection(\n        syncCommand.getSlipStreamEncodedPacketData(),\n      );\n\n      let responseReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n\n      try {\n        if (!this.connection.commandResponseStream) {\n          throw new Error(`No command response stream available.`);\n        }\n        responseReader = this.connection.commandResponseStream.getReader();\n\n        const timeoutPromise = sleep(timeoutPerAttempt).then(() => {\n          throw new Error(`Timeout after ${timeoutPerAttempt}ms`);\n        });\n\n        while (true) {\n          const { value, done } = await Promise.race([\n            responseReader.read(),\n            timeoutPromise,\n          ]);\n\n          if (done) {\n            throw new Error(\"Stream closed unexpectedly while syncing.\");\n          }\n\n          if (value) {\n            try {\n              const responsePacket = new EspCommandPacket();\n              responsePacket.parseResponse(value);\n\n              if (responsePacket.command === EspCommand.SYNC) {\n                console.log(\"SYNCED successfully.\", responsePacket);\n                this.connection.synced = true;\n                this.dispatchEvent(\n                  new CustomEvent(\"sync-progress\", {\n                    detail: { progress: 100 },\n                  }),\n                );\n                return true;\n              }\n            } catch {\n              // Ignore parsing errors and continue reading from the stream\n            }\n          }\n        }\n      } catch (e) {\n        console.log(`Sync attempt ${i + 1} failed.`, e);\n      } finally {\n        if (responseReader) {\n          responseReader.releaseLock();\n        }\n      }\n\n      await sleep(100);\n    }\n\n    console.log(\"Failed to sync with the device.\");\n    this.connection.synced = false;\n    return false;\n  }\n\n  public async detectChip(): Promise<ChipFamily> {\n    if (!this.connection.synced) {\n      throw new Error(\"Device must be synced to detect chip type.\");\n    }\n    const CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000;\n    const readRegCmd = new EspCommandReadReg(CHIP_DETECT_MAGIC_REG_ADDR);\n    await this.writeToConnection(readRegCmd.getSlipStreamEncodedPacketData());\n    const response = await this.readResponse(EspCommand.READ_REG);\n\n    const magicValue = response.value;\n\n    const numericChipValues = Object.values(ChipFamily).filter(\n      (v) => typeof v === \"number\",\n    ) as ChipFamily[];\n\n    const chip =\n      numericChipValues.find((c) => c === magicValue) || ChipFamily.UNKNOWN;\n\n    this.connection.chip = chip;\n    console.log(\n      `Detected chip: ${ChipFamily[chip]} (Magic value: ${toHex(new Uint8Array(new Uint32Array([magicValue]).buffer))})`,\n    );\n\n    if (chip === ChipFamily.UNKNOWN) {\n      throw new Error(\"Could not detect a supported chip family.\");\n    }\n    return chip;\n  }\n\n  public async loadToRam(\n    binary: Uint8Array,\n    offset: number,\n    execute = false,\n    entryPoint = 0,\n  ) {\n    console.log(\n      `Loading binary to RAM at offset ${toHex(new Uint8Array(new Uint32Array([offset]).buffer))}`,\n    );\n    const packetSize = 1460;\n    const numPackets = Math.ceil(binary.length / packetSize);\n\n    const memBeginCmd = new EspCommandMemBegin(\n      binary.length,\n      numPackets,\n      packetSize,\n      offset,\n    );\n    await this.writeToConnection(memBeginCmd.getSlipStreamEncodedPacketData());\n    await this.readResponse(EspCommand.MEM_BEGIN);\n\n    for (let i = 0; i < numPackets; i++) {\n      const memDataCmd = new EspCommandMemData(binary, i, packetSize);\n      await this.writeToConnection(memDataCmd.getSlipStreamEncodedPacketData());\n      await this.readResponse(EspCommand.MEM_DATA, 1000);\n    }\n\n    if (execute) {\n      console.log(`Executing from entry point ${entryPoint}`);\n      const memEndCmd = new EspCommandMemEnd(1, entryPoint);\n      await this.writeToConnection(memEndCmd.getSlipStreamEncodedPacketData());\n      await this.readResponse(EspCommand.MEM_END);\n    }\n  }\n\n  /**\n   * Fetches the stub for the given chip family from the bundled JSON files.\n   * @param chip The chip family to fetch the stub for.\n   * @returns A promise that resolves to the Stub object.\n   */\n  private async getStubForChip(chip: ChipFamily): Promise<Stub> {\n    const stub = STUB_FILES[chip];\n    if (!stub) {\n      throw new Error(`No stub file mapping for chip: ${ChipFamily[chip]}`);\n    }\n    return stub;\n  }\n\n  private async uploadStub(stub: Stub): Promise<void> {\n    const text = base64ToUint8Array(stub.text);\n    const data = base64ToUint8Array(stub.data);\n\n    await this.loadToRam(text, stub.text_start, false);\n    await this.loadToRam(data, stub.data_start, false);\n\n    console.log(`Starting stub at entry point 0x${stub.entry.toString(16)}...`);\n    const memEndCmd = new EspCommandMemEnd(1, stub.entry);\n    await this.writeToConnection(memEndCmd.getSlipStreamEncodedPacketData());\n\n    await this.readResponse(EspCommand.MEM_END);\n    console.log(\"Stub started successfully.\");\n\n    await this.awaitOhaiResponse();\n  }\n\n  private async awaitOhaiResponse(timeout = 2000): Promise<void> {\n    let responseReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n    // The \"OHAI\" payload is 4 bytes: 0x4F, 0x48, 0x41, 0x49\n    const ohaiPacket = new Uint8Array([0x4f, 0x48, 0x41, 0x49]);\n\n    try {\n      if (!this.connection.commandResponseStream) {\n        throw new Error(\"No command response stream available.\");\n      }\n      responseReader = this.connection.commandResponseStream.getReader();\n\n      const timeoutPromise = sleep(timeout).then(() => {\n        throw new Error(\n          `Timeout: Did not receive \"OHAI\" from stub within ${timeout}ms.`,\n        );\n      });\n\n      console.log(\"Waiting for 'OHAI' packet from stub...\");\n\n      while (true) {\n        const { value, done } = await Promise.race([\n          responseReader.read(),\n          timeoutPromise,\n        ]);\n\n        if (done) {\n          throw new Error(\n            \"Stream closed unexpectedly while waiting for 'OHAI'.\",\n          );\n        }\n\n        // Compare the received packet with the expected \"OHAI\" signature\n        if (value && value.length === ohaiPacket.length) {\n          if (value.every((byte, index) => byte === ohaiPacket[index])) {\n            console.log(\"'OHAI' packet received, stub confirmed.\");\n            return; // Success\n          }\n        }\n      }\n    } finally {\n      if (responseReader) {\n        responseReader.releaseLock();\n      }\n    }\n  }\n\n  private async readResponse(\n    expectedCommand: EspCommand,\n    timeout = 2000,\n  ): Promise<EspCommandPacket> {\n    let responseReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n    try {\n      if (!this.connection.commandResponseStream) {\n        throw new Error(`No command response stream available.`);\n      }\n      responseReader = this.connection.commandResponseStream.getReader();\n      const timeoutPromise = sleep(timeout).then(() => {\n        throw new Error(\n          `Timeout: No response received for command ${EspCommand[expectedCommand]} within ${timeout}ms.`,\n        );\n      });\n\n      while (true) {\n        const { value, done } = await Promise.race([\n          responseReader.read(),\n          timeoutPromise,\n        ]);\n\n        if (done) {\n          throw new Error(\n            \"Stream closed unexpectedly while awaiting response.\",\n          );\n        }\n\n        if (value) {\n          try {\n            const responsePacket = new EspCommandPacket();\n            responsePacket.parseResponse(value);\n\n            if (\n              responsePacket.direction === EspPacketDirection.RESPONSE &&\n              responsePacket.command === expectedCommand\n            ) {\n              if (responsePacket.error > 0) {\n                throw new Error(\n                  `Device returned error for ${EspCommand[expectedCommand]\n                  }: ${responsePacket.getErrorMessage(responsePacket.error)}`,\n                );\n              }\n              return responsePacket;\n            }\n          } catch {\n            // Ignore parsing errors and continue reading\n          }\n        }\n      }\n    } finally {\n      if (responseReader) {\n        responseReader.releaseLock();\n      }\n    }\n  }\n\n  public async flashPartition(partition: Partition) {\n    console.log(\n      `Flashing partition: ${partition.filename}, offset: ${toHex(\n        new Uint8Array(new Uint32Array([partition.offset]).buffer),\n      )}`,\n    );\n    const packetSize = 4096;\n    const numPackets = Math.ceil(partition.binary.length / packetSize);\n\n    const flashBeginCmd = new EspCommandFlashBegin(\n      partition.binary,\n      partition.offset,\n      packetSize,\n      numPackets,\n    );\n    await this.writeToConnection(\n      flashBeginCmd.getSlipStreamEncodedPacketData(),\n    );\n    await this.readResponse(EspCommand.FLASH_BEGIN);\n    console.log(\"FLASH_BEGIN successful.\");\n\n    for (let i = 0; i < numPackets; i++) {\n      const flashDataCmd = new EspCommandFlashData(\n        partition.binary,\n        i,\n        packetSize,\n      );\n      await this.writeToConnection(\n        flashDataCmd.getSlipStreamEncodedPacketData(),\n      );\n\n      this.dispatchEvent(\n        new CustomEvent(\"flash-progress\", {\n          detail: {\n            progress: ((i + 1) / numPackets) * 100,\n            partition: partition,\n          },\n        }),\n      );\n\n      console.log(\n        `[${partition.filename}] Writing block ${i + 1}/${numPackets}`,\n      );\n      await this.readResponse(EspCommand.FLASH_DATA, 5000);\n    }\n    console.log(`Flash data for ${partition.filename} sent successfully.`);\n  }\n\n  /**\n   * Main method to flash a complete image.\n   * @param image The ESPImage to flash.\n   */\n  public async flashImage(image: ESPImage) {\n    if (!this.connection.connected) {\n      throw new Error(\"Device is not connected.\");\n    }\n\n    if (!this.connection.synced) {\n      const synced = await this.sync();\n      if (!synced) {\n        throw new Error(\n          \"ESP32 Needs to Sync before flashing. Hold the `boot` button on the device during sync attempts.\",\n        );\n      }\n    }\n\n    if (!this.connection.chip) {\n      await this.detectChip();\n    }\n\n    const stub = await this.getStubForChip(this.connection.chip!);\n    await this.uploadStub(stub);\n\n    const attachCmd = new EspCommandSpiAttach();\n    await this.writeToConnection(attachCmd.getSlipStreamEncodedPacketData());\n    await this.readResponse(EspCommand.SPI_ATTACH);\n    console.log(\"SPI_ATTACH successful.\");\n\n    const setParamsCmd = new EspCommandSpiSetParams();\n    await this.writeToConnection(setParamsCmd.getSlipStreamEncodedPacketData());\n    await this.readResponse(EspCommand.SPI_SET_PARAMS);\n    console.log(\"SPI_SET_PARAMS successful.\");\n\n    const totalSize = image.partitions.reduce(\n      (acc, part) => acc + part.binary.length,\n      0,\n    );\n    let flashedSize = 0;\n\n    for (const partition of image.partitions) {\n      const originalDispatchEvent = this.dispatchEvent;\n      this.dispatchEvent = (event: Event) => {\n        if (event.type === \"flash-progress\" && \"detail\" in event) {\n          const partitionFlashed =\n            (partition.binary.length * (event as CustomEvent).detail.progress) /\n            100;\n          originalDispatchEvent.call(\n            this,\n            new CustomEvent(\"flash-image-progress\", {\n              detail: {\n                progress: ((flashedSize + partitionFlashed) / totalSize) * 100,\n                partition: partition,\n              },\n            }),\n          );\n        }\n        return originalDispatchEvent.call(this, event);\n      };\n\n      await this.flashPartition(partition);\n      flashedSize += partition.binary.length;\n      this.dispatchEvent = originalDispatchEvent;\n    }\n\n    this.dispatchEvent(\n      new CustomEvent(\"flash-image-progress\", {\n        detail: { progress: 100 },\n      }),\n    );\n\n    console.log(\"Flashing complete. Resetting device...\");\n    await this.sendResetPulse();\n    console.log(\"Device has been reset.\");\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Partition } from \"../partition/partition\";\n\nexport class BinFilePartition implements Partition {\n  binary: Uint8Array = new Uint8Array(0);\n\n  constructor(\n    public readonly offset: number,\n    public readonly filename: string,\n  ) {}\n\n  async load(): Promise<boolean> {\n    try {\n      const response = await fetch(this.filename);\n      if (!response.ok) {\n        console.error(\n          `Failed to fetch ${this.filename}: ${response.statusText}`,\n        );\n        return false;\n      }\n      this.binary = new Uint8Array(await response.arrayBuffer());\n      return true;\n    } catch (e) {\n      console.error(`Error loading file ${this.filename}:`, e);\n      return false;\n    }\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Partition } from \"../partition/partition\";\nimport { BinFilePartition } from \"./bin-file-partition\";\n\nexport class ESPImage {\n  partitions: Array<Partition> = [];\n\n  addBootloader(fileName: string) {\n    this.partitions.push(new BinFilePartition(0x1000, fileName));\n  }\n\n  addPartitionTable(fileName: string) {\n    this.partitions.push(new BinFilePartition(0x8000, fileName));\n  }\n\n  addApp(fileName: string) {\n    this.partitions.push(new BinFilePartition(0x10000, fileName));\n  }\n\n  addPartition(partition: Partition) {\n    this.partitions.push(partition);\n  }\n}\n","/**\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * CRCTable copied from https://github.com/espressif/esp-idf/blob/master/components/nvs_flash/mock/int/crc.cpp\n * Licenced under Apache 2.0, Copyright: 2015-2016 Espressif Systems (Shanghai) PTE LTD\n * Removed L notation from all entries.\n */\nconst crc32Table: number[] = [\n  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,\n  0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\n  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,\n  0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\n  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n  0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,\n  0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,\n  0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,\n  0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,\n  0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\n  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,\n  0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n  0xb7bd5c3b, 0xc0ba6cad,\n\n  0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af,\n  0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2,\n  0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,\n  0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9,\n  0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,\n  0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,\n  0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,\n  0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,\n  0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,\n  0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226,\n  0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d,\n  0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,\n  0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70,\n  0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n  0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,\n  0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,\n  0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a,\n  0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,\n  0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1,\n  0x5a05df1b, 0x2d02ef8d,\n];\n\n/**\n * CRC function copied and adapted from: https://github.com/SheetJS/js-crc32/blob/master/crc32.js\n * Licencsed under Apache 2.0: https://github.com/SheetJS/js-crc32/blob/master/LICENSE\n * Changes made:\n * - Typescript notation added.\n * - Referencing above CRC32 Table.\n * - Returns Uint8Array from computed value.\n */\nexport function crc32(buf: Uint8Array, seed = 0xffffffff): Uint8Array {\n  let C = seed ^ -1;\n  const L = buf.length - 7;\n  let i = 0;\n  for (i = 0; i < L; ) {\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n    C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n  }\n  while (i < L + 7) C = (C >>> 8) ^ crc32Table[(C ^ buf[i++]) & 0xff];\n  C = C ^ -1;\n  const buffer = new ArrayBuffer(4);\n  const view = new DataView(buffer);\n  view.setUint32(0, C, true);\n  return new Uint8Array(buffer);\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum NvsType {\n  U8 = 0x01,\n  I8 = 0x11,\n  U16 = 0x02,\n  I16 = 0x12,\n  U32 = 0x04,\n  I32 = 0x14,\n  U64 = 0x08,\n  I64 = 0x18,\n  STR = 0x21,\n  BLOB = 0x42,\n  ANY = 0xff,\n}\n\n// Values correspond to the NVS documentation.\nexport enum NvsEntryState {\n  Empty = 0b11,\n  Written = 0b10,\n  Erased = 0b00,\n}\n\nexport class NVSSettings {\n  static readonly BLOCK_SIZE: number = 32;\n  static readonly PAGE_SIZE: number = 4096;\n  static readonly PAGE_MAX_ENTRIES: number = 126;\n  static readonly PAGE_ACTIVE: number = 0xfffffffe;\n  static readonly PAGE_FULL: number = 0xfffffffc;\n  static readonly NVS_VERSION: number = 0xfe; // version 2\n  static readonly DEFAULT_NAMESPACE: string = \"storage\";\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { crc32 } from \"../utils/crc32\";\nimport { NVSSettings, NvsType } from \"./nvs-settings\";\n\nconst NVS_BLOCK_SIZE = NVSSettings.BLOCK_SIZE;\n\nexport class NvsEntry implements NvsKeyValue {\n  namespaceIndex: number;\n  type: NvsType;\n  key: string;\n  data: string | number;\n  chunkIndex: number;\n\n  headerNamespace: Uint8Array;\n  headerType: Uint8Array;\n  headerSpan: Uint8Array;\n  headerChunkIndex: Uint8Array;\n  headerCRC32: Uint8Array;\n  headerKey: Uint8Array;\n  headerData: Uint8Array;\n  headerDataSize: Uint8Array;\n  headerDataCRC32: Uint8Array;\n\n  headerBuffer: Uint8Array;\n  dataBuffer: Uint8Array;\n\n  entriesNeeded = 0;\n\n  constructor(entry: NvsKeyValue) {\n    this.namespaceIndex = entry.namespaceIndex;\n    this.type = entry.type;\n    this.data = entry.data;\n    this.chunkIndex = 0xff; // Default for non-blob types\n\n    // Validate key length before modification\n    if (entry.key.length > 15) {\n      throw Error(\n        `NVS max key length is 15, received '${entry.key}' of length ${entry.key.length}`,\n      );\n    }\n    this.key = entry.key + \"\\0\";\n\n    // Initialize buffers\n    this.headerBuffer = new Uint8Array(NVS_BLOCK_SIZE);\n    this.headerNamespace = new Uint8Array(this.headerBuffer.buffer, 0, 1);\n    this.headerType = new Uint8Array(this.headerBuffer.buffer, 1, 1);\n    this.headerSpan = new Uint8Array(this.headerBuffer.buffer, 2, 1);\n    this.headerChunkIndex = new Uint8Array(this.headerBuffer.buffer, 3, 1);\n    this.headerCRC32 = new Uint8Array(this.headerBuffer.buffer, 4, 4);\n    this.headerKey = new Uint8Array(this.headerBuffer.buffer, 8, 16);\n    this.headerData = new Uint8Array(this.headerBuffer.buffer, 24, 8);\n    this.headerDataSize = new Uint8Array(this.headerBuffer.buffer, 24, 4);\n    this.headerDataCRC32 = new Uint8Array(this.headerBuffer.buffer, 28, 4);\n    this.dataBuffer = new Uint8Array(0);\n\n    // Process and populate data and header\n    this.setEntryData();\n    this.setEntryHeader();\n    this.setEntryHeaderCRC();\n  }\n\n  private setEntryHeader() {\n    const encoder = new TextEncoder();\n    this.headerNamespace.set([this.namespaceIndex]);\n    this.headerType.set([this.type]);\n    this.headerSpan.set([this.entriesNeeded]);\n    this.headerChunkIndex.set([this.chunkIndex]);\n    this.headerKey.set(encoder.encode(this.key));\n  }\n\n  private setEntryData() {\n    if (this.type === NvsType.STR) {\n      this.setStringEntry();\n    } else if (typeof this.data === \"number\") {\n      this.setPrimitiveEntry();\n    } else {\n      throw new Error(\"Unsupported data type for NVS entry.\");\n    }\n  }\n\n  // In src/nvs/nvs-entry.ts\n\n  private setStringEntry() {\n    if (typeof this.data === \"string\") {\n      // FIX: Fill the entire 8-byte data field with 0xff for correct padding.\n      this.headerData.fill(0xff);\n\n      const valueWithTerminator = this.data + \"\\0\";\n      const encoder = new TextEncoder();\n      const data = encoder.encode(valueWithTerminator);\n\n      if (data.length > 4000) {\n        throw new Error(\"String values are limited to 4000 bytes.\");\n      }\n\n      this.entriesNeeded = 1 + Math.ceil(data.length / NVSSettings.BLOCK_SIZE);\n      this.dataBuffer = new Uint8Array(\n        (this.entriesNeeded - 1) * NVSSettings.BLOCK_SIZE,\n      ).fill(0xff);\n      this.dataBuffer.set(data);\n\n      const dataSizeBuffer = new ArrayBuffer(2);\n      const dataSizeView = new DataView(dataSizeBuffer);\n      // The true parameter indicates little-endian byte order.\n      dataSizeView.setUint16(0, data.length, true);\n\n      // Set the size in the first 2 bytes of the 8-byte headerData field.\n      this.headerData.set(new Uint8Array(dataSizeBuffer), 0);\n      // Set the data CRC in the last 4 bytes of the 8-byte headerData field.\n      this.headerDataCRC32.set(crc32(data));\n    }\n  }\n\n  private setPrimitiveEntry() {\n    if (typeof this.data === \"number\") {\n      this.entriesNeeded = 1;\n      // First, fill the entire 8-byte data field with 0xff for correct padding\n      this.headerData.fill(0xff);\n\n      const dataView = new DataView(\n        this.headerData.buffer,\n        this.headerData.byteOffset,\n        8,\n      );\n\n      switch (this.type) {\n        case NvsType.U8:\n          dataView.setUint8(0, this.data);\n          break;\n        case NvsType.I8:\n          dataView.setInt8(0, this.data);\n          break;\n        case NvsType.U16:\n          dataView.setUint16(0, this.data, true);\n          break;\n        case NvsType.I16:\n          dataView.setInt16(0, this.data, true);\n          break;\n        case NvsType.U32:\n          dataView.setUint32(0, this.data, true);\n          break;\n        case NvsType.I32:\n          dataView.setInt32(0, this.data, true);\n          break;\n        case NvsType.U64:\n          dataView.setBigUint64(0, BigInt(this.data), true);\n          break;\n        case NvsType.I64:\n          dataView.setBigInt64(0, BigInt(this.data), true);\n          break;\n        default:\n          throw new Error(`Unsupported primitive type: ${this.type}`);\n      }\n    }\n  }\n\n  private setEntryHeaderCRC() {\n    const crcData = new Uint8Array(28);\n    crcData.set(this.headerBuffer.slice(0, 4), 0);\n    crcData.set(this.headerBuffer.slice(8, 32), 4);\n    this.headerCRC32.set(crc32(crcData));\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NvsEntryState } from \"./nvs-settings\";\n\n/**\n * A helper utility to manage the 126-entry, 252-bit state bitmap.\n * Each entry uses 2 bits to represent its state.\n */\nexport const EntryStateBitmap = {\n  /**\n   * Updates the state for a given entry in the bitmap.\n   * @param currentBitmap The current state bitmap as a BigInt.\n   * @param entryIndex The index of the entry to update (0-125).\n   * @param newState The new state for the entry.\n   * @returns The updated bitmap as a BigInt.\n   */\n  setState(\n    currentBitmap: bigint,\n    entryIndex: number,\n    newState: NvsEntryState,\n  ): bigint {\n    if (entryIndex < 0 || entryIndex >= 126) {\n      throw new Error(\"Entry index is out of bounds.\");\n    }\n\n    const bitPosition = BigInt(entryIndex * 2);\n\n    // 1. Create a mask to clear the 2 bits for the target entry.\n    const clearMask = ~(0b11n << bitPosition);\n    const clearedBitmap = currentBitmap & clearMask;\n\n    // 2. Create the new value shifted to the correct position.\n    const newValue = BigInt(newState) << bitPosition;\n\n    // 3. Combine the cleared bitmap with the new state value.\n    return clearedBitmap | newValue;\n  },\n};\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NvsEntry } from \"./nvs-entry\";\nimport { crc32 } from \"../utils/crc32\";\nimport { NVSSettings, NvsType, NvsEntryState } from \"./nvs-settings\";\nimport { EntryStateBitmap } from \"./state-bitmap\";\n\nexport class NVSPage {\n  private entryNumber = 0;\n  private pageBuffer: Uint8Array;\n  private pageHeader: Uint8Array;\n  private stateBitmap = BigInt(\n    \"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\",\n  );\n  private entries: NvsEntry[] = [];\n  private itemHashMap = new Map<number, number>();\n\n  private headerPageState: Uint8Array;\n  private headerPageNumber: Uint8Array;\n  private headerVersion: Uint8Array;\n  private headerCRC32: Uint8Array;\n  private isStateLocked = false;\n\n  constructor(\n    public pageNumber: number,\n    public version: number,\n  ) {\n    this.pageBuffer = new Uint8Array(NVSSettings.PAGE_SIZE).fill(0xff);\n    this.pageHeader = new Uint8Array(this.pageBuffer.buffer, 0, 32);\n    this.headerPageState = new Uint8Array(this.pageHeader.buffer, 0, 4);\n    this.headerPageNumber = new Uint8Array(this.pageHeader.buffer, 4, 4);\n    this.headerVersion = new Uint8Array(this.pageHeader.buffer, 8, 1);\n    this.headerCRC32 = new Uint8Array(this.pageHeader.buffer, 28, 4);\n    this.setPageHeader();\n  }\n\n  private setPageHeader() {\n    this.setPageState(\"ACTIVE\");\n    // Use DataView to correctly set the 32-bit page number in little-endian format\n    const pageNumView = new DataView(\n      this.headerPageNumber.buffer,\n      this.headerPageNumber.byteOffset,\n      4,\n    );\n    pageNumView.setUint32(0, this.pageNumber, true);\n    this.headerVersion.set([this.version]);\n    this.updateHeaderCrc();\n  }\n\n  private updateHeaderCrc() {\n    const crcData: Uint8Array = this.pageHeader.slice(4, 28);\n    this.headerCRC32.set(crc32(crcData));\n  }\n\n  private _calculateItemHash(\n    namespaceIndex: number,\n    key: string,\n    chunkIndex: number,\n  ): number {\n    const hashData = `${namespaceIndex}:${key}:${chunkIndex}`;\n    const fullCrc = crc32(new TextEncoder().encode(hashData));\n    return new DataView(fullCrc.buffer).getUint32(0, true) & 0x00ffffff;\n  }\n\n  private getNVSEncoding(value: number | string): NvsType {\n    if (typeof value === \"string\") {\n      return NvsType.STR;\n    }\n    const isNegative = value < 0;\n    const absValue = Math.abs(value);\n    if (isNegative) {\n      if (absValue <= 0x80) return NvsType.I8;\n      if (absValue <= 0x8000) return NvsType.I16;\n      if (absValue <= 0x80000000) return NvsType.I32;\n      return NvsType.I64;\n    } else {\n      if (absValue <= 0xff) return NvsType.U8;\n      if (absValue <= 0xffff) return NvsType.U16;\n      if (absValue <= 0xffffffff) return NvsType.U32;\n      return NvsType.U64;\n    }\n  }\n\n  public writeEntry(\n    key: string,\n    data: string | number,\n    namespaceIndex: number,\n  ): NvsEntry {\n    if (this.isStateLocked) {\n      // FIX: This error message now matches the test expectation.\n      throw new Error(\"Page is full and locked. Cannot write new entries.\");\n    }\n\n    const entryKv: NvsKeyValue = {\n      namespaceIndex,\n      key,\n      data,\n      type: this.getNVSEncoding(data),\n    };\n    const entry = new NvsEntry(entryKv);\n\n    if (entry.entriesNeeded + this.entryNumber > NVSSettings.PAGE_MAX_ENTRIES) {\n      this.setPageState(\"FULL\");\n      throw new Error(\"Entry doesn't fit on the page\");\n    }\n\n    const hash = this._calculateItemHash(namespaceIndex, key, entry.chunkIndex);\n    this.itemHashMap.set(hash, this.entryNumber);\n    this.entries.push(entry);\n\n    for (let i = 0; i < entry.entriesNeeded; i++) {\n      this.stateBitmap = EntryStateBitmap.setState(\n        this.stateBitmap,\n        this.entryNumber + i,\n        NvsEntryState.Written,\n      );\n    }\n\n    this.entryNumber += entry.entriesNeeded;\n    return entry;\n  }\n\n  public findEntry(\n    key: string,\n    namespaceIndex: number,\n    chunkIndex = 0xff,\n  ): NvsEntry | undefined {\n    const hash = this._calculateItemHash(namespaceIndex, key, chunkIndex);\n    const potentialIndex = this.itemHashMap.get(hash);\n\n    if (potentialIndex !== undefined) {\n      const entry = this.entries[potentialIndex];\n      if (\n        entry &&\n        entry.key === key &&\n        entry.namespaceIndex === namespaceIndex &&\n        entry.chunkIndex === chunkIndex\n      ) {\n        return entry;\n      }\n    }\n\n    return this.entries.find(\n      (e) =>\n        e.key === key &&\n        e.namespaceIndex === namespaceIndex &&\n        e.chunkIndex === chunkIndex,\n    );\n  }\n\n  public setPageState(state: NvsPageState) {\n    if (state === \"FULL\") {\n      this.headerPageState.set(\n        new Uint8Array(new Uint32Array([NVSSettings.PAGE_FULL]).buffer),\n      );\n      this.isStateLocked = true;\n    } else if (state === \"ACTIVE\") {\n      this.headerPageState.set(\n        new Uint8Array(new Uint32Array([NVSSettings.PAGE_ACTIVE]).buffer),\n      );\n    } else {\n      throw Error(\"Invalid page state requested\");\n    }\n    this.updateHeaderCrc();\n  }\n\n  public getData(): Uint8Array {\n    // Write header and state bitmap\n    const sbm = new Uint8Array(NVSSettings.BLOCK_SIZE).fill(0xff);\n    new DataView(sbm.buffer).setBigUint64(0, this.stateBitmap, true);\n    this.pageBuffer.set(this.pageHeader, 0);\n    this.pageBuffer.set(sbm, NVSSettings.BLOCK_SIZE);\n\n    // Write entries\n    let currentEntrySlot = 0;\n    for (const entry of this.entries) {\n      const headerOffset = (2 + currentEntrySlot) * NVSSettings.BLOCK_SIZE;\n      this.pageBuffer.set(entry.headerBuffer, headerOffset);\n\n      if (entry.dataBuffer.length > 0) {\n        const dataOffset = (2 + currentEntrySlot + 1) * NVSSettings.BLOCK_SIZE;\n        this.pageBuffer.set(entry.dataBuffer, dataOffset);\n      }\n\n      currentEntrySlot += entry.entriesNeeded;\n    }\n\n    return this.pageBuffer;\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Partition } from \"../partition/partition\";\nimport { NVSPage } from \"./nvs-page\";\nimport { NVSSettings } from \"./nvs-settings\";\n\nexport class NVSPartition implements Partition {\n  private namespaces: string[] = [];\n  private pages: NVSPage[] = [];\n\n  constructor(\n    public readonly offset: number,\n    public readonly filename: string,\n    public size: number = 0x3000,\n  ) {\n    // Namespace at index 0 is reserved. We add a placeholder.\n    this.namespaces.push(\"RESERVED_NS_0\");\n    this.newPage();\n  }\n\n  private newPage(): NVSPage {\n    const lastPage = this.getLastPage();\n    if (lastPage) {\n      lastPage.setPageState(\"FULL\");\n    }\n    const index = this.pages.length;\n    const nvsPage = new NVSPage(index, NVSSettings.NVS_VERSION);\n    this.pages.push(nvsPage);\n    return nvsPage;\n  }\n\n  private getLastPage(): NVSPage | null {\n    if (this.pages.length === 0) {\n      return null;\n    }\n    return this.pages[this.pages.length - 1];\n  }\n\n  private getNameSpaceIndex(namespace: string): number {\n    const existingIndex = this.namespaces.indexOf(namespace);\n    if (existingIndex !== -1) {\n      return existingIndex;\n    }\n\n    // Add as new namespace.\n    if (this.namespaces.length >= 254) {\n      throw new Error(\"Maximum number of namespaces (254) reached.\");\n    }\n    const newIndex = this.namespaces.length;\n    this.namespaces.push(namespace);\n\n    try {\n      this.write(namespace, newIndex, 0); // Write to namespace 0\n    } catch (e) {\n      // This logic will be hit if writing the namespace entry itself fills the page.\n      console.log(\"Page is full, creating new\", e);\n      this.newPage();\n      this.write(namespace, newIndex, 0);\n    }\n    return newIndex;\n  }\n\n  public get binary(): Uint8Array {\n    const buffer = new Uint8Array(this.size).fill(0xff);\n    let offset = 0;\n    for (const page of this.pages) {\n      const pageBuffer = page.getData();\n      buffer.set(pageBuffer, offset);\n      offset += pageBuffer.length;\n    }\n    return buffer;\n  }\n\n  public writeEntry(namespace: string, key: string, data: string | number) {\n    const namespaceIndex = this.getNameSpaceIndex(namespace);\n    this.write(key, data, namespaceIndex);\n  }\n\n  // Private write helper to avoid recursive loop in namespace creation\n  private write(key: string, data: string | number, namespaceIndex: number) {\n    try {\n      const page = this.getLastPage();\n      if (!page) throw new Error(\"No active page available.\");\n      page.writeEntry(key, data, namespaceIndex);\n    } catch (error) {\n      if (\n        error instanceof Error &&\n        error.message.startsWith(\"Entry doesn't fit\")\n      ) {\n        // If the current page is full, create a new one and retry.\n        const page = this.newPage();\n        page.writeEntry(key, data, namespaceIndex);\n      } else {\n        // Re-throw other errors\n        throw error;\n      }\n    }\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n  PartitionDefinition,\n  PartitionFlags,\n  PartitionType,\n} from \"./partition-types\";\n\nconst MAGIC_BYTES = new Uint8Array([0xaa, 0x50]);\nconst SIZEOF_STRUCT = 32;\n\nexport class PartitionEntry {\n  name: string;\n  type: PartitionType;\n  subType: number;\n  offset: number;\n  size: number;\n  flags: PartitionFlags;\n\n  constructor(definition: PartitionDefinition) {\n    if (definition.name.length > 16) {\n      throw new Error(\"Partition name cannot be longer than 16 characters.\");\n    }\n    this.name = definition.name;\n    this.type = definition.type;\n    this.subType = definition.subType;\n    this.offset = definition.offset || 0;\n    this.size = definition.size;\n    this.flags = {\n      encrypted: definition.flags?.encrypted || false,\n      readonly: definition.flags?.readonly || false,\n    };\n  }\n\n  public toBinary(): Uint8Array {\n    const buffer = new ArrayBuffer(SIZEOF_STRUCT);\n    const view = new DataView(buffer);\n    const textEncoder = new TextEncoder();\n\n    view.setUint8(0, MAGIC_BYTES[0]);\n    view.setUint8(1, MAGIC_BYTES[1]);\n    view.setUint8(2, this.type);\n    view.setUint8(3, this.subType);\n    view.setUint32(4, this.offset, true);\n    view.setUint32(8, this.size, true);\n\n    const encodedName = textEncoder.encode(this.name);\n    new Uint8Array(buffer, 12, 16).set(encodedName);\n\n    let flags = 0;\n    if (this.flags.encrypted) {\n      flags |= 1;\n    }\n    if (this.flags.readonly) {\n      flags |= 2;\n    }\n    view.setUint32(28, flags, true);\n\n    return new Uint8Array(buffer);\n  }\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport enum PartitionType {\n  APP = 0x00,\n  DATA = 0x01,\n}\n\nexport enum AppPartitionSubType {\n  FACTORY = 0x00,\n  OTA_0 = 0x10,\n  OTA_1 = 0x11,\n  OTA_2 = 0x12,\n  OTA_3 = 0x13,\n  OTA_4 = 0x14,\n  OTA_5 = 0x15,\n  OTA_6 = 0x16,\n  OTA_7 = 0x17,\n  OTA_8 = 0x18,\n  OTA_9 = 0x19,\n  OTA_10 = 0x1a,\n  OTA_11 = 0x1b,\n  OTA_12 = 0x1c,\n  OTA_13 = 0x1d,\n  OTA_14 = 0x1e,\n  OTA_15 = 0x1f,\n  TEST = 0x20,\n}\n\nexport enum DataPartitionSubType {\n  OTA = 0x00,\n  PHY = 0x01,\n  NVS = 0x02,\n  NVS_KEYS = 0x04,\n  SPIFFS = 0x82,\n}\n\nexport interface PartitionFlags {\n  encrypted: boolean;\n  readonly: boolean;\n}\n\nexport interface PartitionDefinition {\n  name: string;\n  type: PartitionType;\n  subType: AppPartitionSubType | DataPartitionSubType;\n  offset?: number;\n  size: number;\n  flags?: Partial<PartitionFlags>;\n}\n","/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Partition } from \"./partition\";\nimport { PartitionEntry } from \"./partition-entry\";\nimport {\n  AppPartitionSubType,\n  DataPartitionSubType,\n  PartitionDefinition,\n  PartitionType,\n} from \"./partition-types\";\nimport SparkMD5 from \"spark-md5\";\n\nconst PARTITION_TABLE_OFFSET = 0x8000;\nconst MAX_PARTITION_LENGTH = 0xc00;\nconst PARTITION_TABLE_SIZE = 0x1000;\nconst MD5_PARTITION_BEGIN = new Uint8Array([\n  0xeb,\n  0xeb,\n  ...Array(14).fill(0xff),\n]);\n\nexport class PartitionTable implements Partition {\n  private entries: PartitionEntry[] = [];\n  public readonly offset = PARTITION_TABLE_OFFSET;\n  public readonly filename = \"partition-table.bin\";\n\n  constructor(definitions: PartitionDefinition[]) {\n    this.processDefinitions(definitions);\n  }\n\n  private processDefinitions(definitions: PartitionDefinition[]) {\n    let lastEnd = PARTITION_TABLE_OFFSET + PARTITION_TABLE_SIZE;\n\n    for (const definition of definitions) {\n      if (!definition.offset) {\n        const alignment =\n          definition.type === PartitionType.APP ? 0x10000 : 0x1000;\n        if (lastEnd % alignment !== 0) {\n          lastEnd += alignment - (lastEnd % alignment);\n        }\n        definition.offset = lastEnd;\n      }\n      this.entries.push(new PartitionEntry(definition));\n      lastEnd = definition.offset + definition.size;\n    }\n  }\n\n  get binary(): Uint8Array {\n    return this.toBinary();\n  }\n\n  public toBinary(enableMD5 = true): Uint8Array {\n    let binary = new Uint8Array();\n    for (const entry of this.entries) {\n      binary = new Uint8Array([...binary, ...entry.toBinary()]);\n    }\n\n    if (enableMD5) {\n      // Use SparkMD5.ArrayBuffer.hash for binary data\n      const checksum = SparkMD5.ArrayBuffer.hash(binary.buffer, true);\n      const checksumBytes = Uint8Array.from(checksum, (c) => c.charCodeAt(0));\n      const md5Entry = new Uint8Array([\n        ...MD5_PARTITION_BEGIN,\n        ...new Uint8Array(checksumBytes),\n      ]);\n      binary = new Uint8Array([...binary, ...md5Entry]);\n    }\n\n    const padding = new Uint8Array(MAX_PARTITION_LENGTH - binary.length).fill(\n      0xff,\n    );\n    return new Uint8Array([...binary, ...padding]);\n  }\n\n  public static singleFactoryAppNoOta(): PartitionTable {\n    return new PartitionTable([\n      {\n        name: \"nvs\",\n        type: PartitionType.DATA,\n        subType: DataPartitionSubType.NVS,\n        size: 0x6000,\n      },\n      {\n        name: \"phy_init\",\n        type: PartitionType.DATA,\n        subType: DataPartitionSubType.PHY,\n        size: 0x1000,\n      },\n      {\n        name: \"factory\",\n        type: PartitionType.APP,\n        subType: AppPartitionSubType.FACTORY,\n        size: 1024 * 1024,\n      },\n    ]);\n  }\n\n  public static factoryAppTwoOtaDefinitions(): PartitionTable {\n    return new PartitionTable([\n      {\n        name: \"nvs\",\n        type: PartitionType.DATA,\n        subType: DataPartitionSubType.NVS,\n        size: 0x4000,\n      },\n      {\n        name: \"otadata\",\n        type: PartitionType.DATA,\n        subType: DataPartitionSubType.OTA,\n        size: 0x2000,\n      },\n      {\n        name: \"phy_init\",\n        type: PartitionType.DATA,\n        subType: DataPartitionSubType.PHY,\n        size: 0x1000,\n      },\n      {\n        name: \"factory\",\n        type: PartitionType.APP,\n        subType: AppPartitionSubType.FACTORY,\n        size: 1024 * 1024,\n      },\n      {\n        name: \"ota_0\",\n        type: PartitionType.APP,\n        subType: AppPartitionSubType.OTA_0,\n        size: 1024 * 1024,\n      },\n      {\n        name: \"ota_1\",\n        type: PartitionType.APP,\n        subType: AppPartitionSubType.OTA_1,\n        size: 1024 * 1024,\n      },\n    ]);\n  }\n}\n"],"mappings":"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;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAEZ;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAAY;AAAA,EAC5D;AAAA,EAAY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","names":["EspCommand","ChipFamily","PartitionType","AppPartitionSubType","DataPartitionSubType","SparkMD5"]}