{"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-data.ts","../src/esp/command.flash-begin.ts","../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 * 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  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\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 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 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 {\n  createLineBreakTransformer,\n  SlipStreamDecoder,\n} from \"./stream-transformers\";\nimport { sleep, toHex } from \"../utils/common\";\nimport { EspCommand, EspCommandPacket, EspPacketDirection } from \"./command\";\nimport { EspCommandSync } from \"./command.sync\";\nimport { EspCommandSpiAttach } from \"./command.spi-attach\";\nimport { EspCommandSpiSetParams } from \"./command.spi-set-params\";\nimport { ESPImage } from \"../image/image\";\nimport { EspCommandFlashData } from \"./command.flash-data\";\nimport { EspCommandFlashBegin } from \"./command.flash-begin\";\nimport { Partition } from \"../partition/partition\";\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 * 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 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\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      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  }\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(), 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 result = await Promise.race([\n            responseReader.read(),\n            timeoutPromise,\n          ]);\n\n          const { value, done } = result;\n\n          if (done) {\n            break;\n          }\n\n          if (value) {\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          }\n        }\n      } catch (e) {\n        console.log(`Sync attempt ${i + 1} timed out.`, 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  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          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 ${\n                  EspCommand[expectedCommand]\n                }: ${responsePacket.getErrorMessage(responsePacket.error)}`,\n              );\n            }\n            return responsePacket;\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  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    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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A,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,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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","names":["EspCommand","PartitionType","AppPartitionSubType","DataPartitionSubType","SparkMD5"]}