@orkestrel/msg 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/src/core/index.cjs +2548 -0
- package/dist/src/core/index.cjs.map +1 -0
- package/dist/src/core/index.d.cts +1350 -0
- package/dist/src/core/index.d.ts +1350 -0
- package/dist/src/core/index.js +2445 -0
- package/dist/src/core/index.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["#liteEntries","#fat","#miniFat","#buildTree","#allocateFat","#allocateMiniFat","#allocateFatAs","#buildDifat","#writeHeader","#writeDirectoryEntries","#writeLargeStreams","#writeMiniStreams","#writeMiniFat","#writeFat","#writeDifat","#splitTree","#view","#byteLength","#totalSectors","#options","#fields","#parseHeader","#bat","#readBat","#xbatCount","#readXbat","#sbat","#readSbat","#properties","#readProperties","#propertyStart","#bigBlockTable","#buildBigBlockTable","#privatePidToKeyed","#innerMSGBurners","#extractFields","#readEntry","#burnFolder","#bigBlockSize","#bigBlockLength","#xBlockLength","#validateHeaderField","#batCount","#sbatStart","#sbatCount","#xbatStart","#batCountInHeader","#blockOffset","#assertBounds","#blockValueAt","#nextBlockInner","#trackSector","#nextBlock","#readEntryName","#readDirectoryEntry","#buildHierarchy","#readSmallBlockData","#nextBlockSmall","#smallBlockChain","#readSmallChainData","#processDirectory","#toFieldData","#str","#bin","#num","#role","#bool","#processSubDirectory","#processDocument","#processPropertyStream","#processNameIdDirectory","#getDirectoryFieldType","#decodeAndAssign","#resolvePidLid","#parseEntryStream","#registerBurnerFolder","#options"],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/helpers.ts","../../../src/core/MSGBurner.ts","../../../src/core/MSGReader.ts","../../../src/core/EmailParser.ts","../../../src/core/factories.ts"],"sourcesContent":["// === MSGReader\n\n/**\n * CFB magic header bytes (0xD0CF11E0A1B11AE1).\n */\nexport const MSG_FILE_HEADER = new Uint8Array([0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1])\n\n/**\n * Sentinel for unused blocks in the FAT.\n */\nexport const MSG_UNUSED_BLOCK = -1\n\n/**\n * Sentinel for end-of-chain in the FAT.\n */\nexport const MSG_END_OF_CHAIN = -2\n\n/**\n * Small sector size (512 bytes).\n */\nexport const MSG_S_BIG_BLOCK_SIZE = 0x0200\n\n/**\n * Small sector size mark in the header (byte at offset 30).\n */\nexport const MSG_S_BIG_BLOCK_MARK = 9\n\n/**\n * Large sector size (4096 bytes).\n */\nexport const MSG_L_BIG_BLOCK_SIZE = 0x1000\n\n/**\n * Large sector size mark in the header (byte at offset 30).\n */\nexport const MSG_L_BIG_BLOCK_MARK = 12\n\n/**\n * Mini-stream sector size (64 bytes).\n */\nexport const MSG_SMALL_BLOCK_SIZE = 0x0040\n\n/**\n * Threshold below which data is stored in the mini-stream.\n */\nexport const MSG_BIG_BLOCK_MIN_DOC_SIZE = 0x1000\n\n/**\n * Header offset: property (directory) start sector.\n */\nexport const MSG_HEADER_PROPERTY_START_OFFSET = 0x30\n\n/**\n * Header offset: BAT sector array start.\n */\nexport const MSG_HEADER_BAT_START_OFFSET = 0x4c\n\n/**\n * Header offset: BAT sector count.\n */\nexport const MSG_HEADER_BAT_COUNT_OFFSET = 0x2c\n\n/**\n * Header offset: SBAT start sector.\n */\nexport const MSG_HEADER_SBAT_START_OFFSET = 0x3c\n\n/**\n * Header offset: SBAT sector count.\n */\nexport const MSG_HEADER_SBAT_COUNT_OFFSET = 0x40\n\n/**\n * Header offset: XBAT (DIFAT) start sector.\n */\nexport const MSG_HEADER_XBAT_START_OFFSET = 0x44\n\n/**\n * Header offset: XBAT (DIFAT) sector count.\n */\nexport const MSG_HEADER_XBAT_COUNT_OFFSET = 0x48\n\n/**\n * No child/sibling index sentinel.\n */\nexport const MSG_PROP_NO_INDEX = -1\n\n/**\n * Maximum recursion depth accepted by the directory hierarchy builder\n * (`MSGReader#buildHierarchy`). Defense-in-depth against a pathological\n * or hostile directory tree — the sibling-chain and visited-set guards\n * already bound each level, this caps the recursion depth itself.\n */\nexport const MSG_MAX_HIERARCHY_DEPTH = 64\n\n/**\n * Directory entry size in bytes.\n */\nexport const MSG_PROPERTY_SIZE = 0x0080\n\n/**\n * Offset within a directory entry: name byte length.\n */\nexport const MSG_PROP_NAME_SIZE_OFFSET = 0x40\n\n/**\n * Offset within a directory entry: object type byte.\n */\nexport const MSG_PROP_TYPE_OFFSET = 0x42\n\n/**\n * Offset within a directory entry: left sibling index.\n */\nexport const MSG_PROP_PREVIOUS_PROPERTY_OFFSET = 0x44\n\n/**\n * Offset within a directory entry: right sibling index.\n */\nexport const MSG_PROP_NEXT_PROPERTY_OFFSET = 0x48\n\n/**\n * Offset within a directory entry: child index.\n */\nexport const MSG_PROP_CHILD_PROPERTY_OFFSET = 0x4c\n\n/**\n * Offset within a directory entry: start sector of stream data.\n */\nexport const MSG_PROP_START_BLOCK_OFFSET = 0x74\n\n/**\n * Offset within a directory entry: stream byte length.\n */\nexport const MSG_PROP_SIZE_OFFSET = 0x78\n\n/**\n * Directory entry type: unallocated.\n */\nexport const MSG_TYPE_UNALLOCATED = 0\n\n/**\n * Directory entry type: storage (folder).\n */\nexport const MSG_TYPE_DIRECTORY = 1\n\n/**\n * Directory entry type: stream (document).\n */\nexport const MSG_TYPE_DOCUMENT = 2\n\n/**\n * Directory entry type: root storage.\n */\nexport const MSG_TYPE_ROOT = 5\n\n/**\n * Name prefix for attachment storage entries.\n */\nexport const MSG_PREFIX_ATTACHMENT = '__attach_version1.0'\n\n/**\n * Name prefix for recipient storage entries.\n */\nexport const MSG_PREFIX_RECIPIENT = '__recip_version1.0'\n\n/**\n * Name prefix for document (substg) stream entries.\n */\nexport const MSG_PREFIX_DOCUMENT = '__substg1.'\n\n/**\n * Name prefix for named property mapping storage.\n */\nexport const MSG_PREFIX_NAMEID = '__nameid_version1.0'\n\n/**\n * MAPI property tag to field name mapping.\n */\nexport const MSG_FIELD_NAME_MAPPING: Readonly<Record<string, string>> = {\n\t// email specific\n\t'001a': 'messageClass',\n\t'0037': 'subject',\n\t'0039': 'clientSubmitTime',\n\t'0070': 'conversationTopic',\n\t'007d': 'headers',\n\t'0c15': 'recipientRole',\n\t'0c1a': 'senderName',\n\t'0c1e': 'senderAddressType',\n\t'0c1f': 'senderEmail',\n\t'0e06': 'messageDeliveryTime',\n\t'0e07': 'messageFlags',\n\t'0e1d': 'normalizedSubject',\n\t'1000': 'body',\n\t'1009': 'compressedRTF',\n\t'1035': 'messageId',\n\t// recipient specific\n\t'3001': 'name',\n\t'3002': 'addressType',\n\t'3003': 'email',\n\t// shared (msg + attachment)\n\t'3007': 'creationTime',\n\t'3008': 'lastModificationTime',\n\t// attachment specific\n\t'3703': 'extension',\n\t'3704': 'fileNameShort',\n\t'3707': 'fileName',\n\t'3712': 'contentId',\n\t'370e': 'mimeType',\n\t// recipient / msg\n\t'39fe': 'smtpAddress',\n\t// msg metadata\n\t'3fd9': 'preview',\n\t'3fde': 'internetCodepage',\n\t'3ff1': 'messageLocaleId',\n\t'3ffa': 'lastModifierName',\n\t'3ffd': 'messageCodepage',\n\t'5d01': 'senderSMTPAddress',\n\t'5d02': 'sentRepresentingSMTPAddress',\n\t'5d0a': 'creatorSMTPAddress',\n\t'5d0b': 'lastModifierSMTPAddress',\n\t'7ffe': 'attachmentHidden',\n\t// contact specific\n\t'3a05': 'generation',\n\t'3a06': 'givenName',\n\t'3a08': 'businessPhone',\n\t'3a09': 'homePhone',\n\t'3a0d': 'location',\n\t'3a11': 'surname',\n\t'3a15': 'postalAddress',\n\t'3a16': 'companyName',\n\t'3a17': 'jobTitle',\n\t'3a18': 'departmentName',\n\t'3a1c': 'mobilePhone',\n\t'3a24': 'businessFax',\n\t'3a26': 'country',\n\t'3a27': 'homeAddressCity',\n\t'3a28': 'stateOrProvince',\n\t'3a29': 'streetAddress',\n\t'3a2a': 'postalCode',\n\t'3a44': 'middleName',\n\t'3a45': 'namePrefix',\n\t'3a51': 'businessHomePage',\n}\n\n/**\n * Full 8-char property tag to field name mapping (for compound tags).\n */\nexport const MSG_FIELD_FULL_NAME_MAPPING: Readonly<Record<string, string>> = {\n\t'1013001f': 'bodyHTML',\n\t'10130102': 'html',\n}\n\n/**\n * MAPI property type tag to decode type mapping.\n */\nexport const MSG_FIELD_TYPE_MAPPING: Readonly<Record<string, string>> = {\n\t'001e': 'string',\n\t'001f': 'unicode',\n\t'0040': 'time',\n\t'0102': 'binary',\n\t'0003': 'integer',\n\t'000b': 'boolean',\n}\n\n/**\n * Attachment data class identifier.\n */\nexport const MSG_FIELD_CLASS_ATTACHMENT_DATA = '3701'\n\n/**\n * Directory field type indicating an embedded MSG.\n */\nexport const MSG_FIELD_DIR_TYPE_INNER_MSG = '000d'\n\n/**\n * MAPI recipient type: TO.\n */\nexport const MSG_MAPI_RECIPIENT_TO = 1\n\n/**\n * MAPI recipient type: CC.\n */\nexport const MSG_MAPI_RECIPIENT_CC = 2\n\n/**\n * MAPI recipient type: BCC.\n */\nexport const MSG_MAPI_RECIPIENT_BCC = 3\n\n/**\n * PidLid property set GUID to LID-to-field-name mapping.\n * Maps well-known MAPI named property sets to their property\n * long IDs and corresponding field names on MSGFieldData.\n */\nexport const MSG_PIDLID_MAPPING: Readonly<Record<string, Readonly<Record<number, string>>>> = {\n\t// PSETID_Common\n\t'00062008-0000-0000-c000-000000000046': {\n\t\t0x00008524: 'votingResponse',\n\t\t0x00008580: 'internetAccountName',\n\t},\n\t// PSETID_Appointment\n\t'00062002-0000-0000-c000-000000000046': {\n\t\t0x0000820d: 'appointmentStart',\n\t\t0x0000820e: 'appointmentEnd',\n\t\t0x00008208: 'appointmentLocation',\n\t\t0x00008234: 'timeZoneDescription',\n\t\t0x00008235: 'clipStart',\n\t\t0x00008236: 'clipEnd',\n\t},\n\t// PSETID_Address\n\t'00062004-0000-0000-c000-000000000046': {\n\t\t0x00008005: 'fileUnder',\n\t\t0x00008010: 'departmentName',\n\t\t0x0000801b: 'workAddress',\n\t\t0x0000802b: 'contactWebPage',\n\t\t0x0000802c: 'yomiFirstName',\n\t\t0x0000802d: 'yomiLastName',\n\t\t0x0000802e: 'yomiCompanyName',\n\t\t0x00008045: 'workAddressStreet',\n\t\t0x00008046: 'workAddressCity',\n\t\t0x00008047: 'workAddressState',\n\t\t0x00008048: 'workAddressPostalCode',\n\t\t0x00008049: 'workAddressCountry',\n\t\t0x00008062: 'instantMessagingAddress',\n\t\t0x00008080: 'primaryEmailDisplayName',\n\t\t0x00008083: 'primaryEmailAddress',\n\t\t0x00008084: 'primaryEmailOriginalDisplayName',\n\t\t0x000080b2: 'fax1AddressType',\n\t\t0x000080b3: 'fax1EmailAddress',\n\t\t0x000080b4: 'fax1OriginalDisplayName',\n\t\t0x000080c2: 'fax2AddressType',\n\t\t0x000080c3: 'fax2EmailAddress',\n\t\t0x000080c4: 'fax2OriginalDisplayName',\n\t\t0x000080d2: 'fax3AddressType',\n\t\t0x000080d3: 'fax3EmailAddress',\n\t\t0x000080d4: 'fax3OriginalDisplayName',\n\t\t0x000080db: 'workAddressCountryCode',\n\t\t0x000080dd: 'addressCountryCode',\n\t},\n\t// PSETID_Meeting\n\t'6ed8da90-450b-101b-98da-00aa003f1305': {\n\t\t0x00000003: 'globalAppointmentId',\n\t\t0x00000028: 'appointmentOldLocation',\n\t},\n}\n\n// === MSGBurner\n\n/**\n * Standard CFB sector size in bytes (512).\n */\nexport const MSG_BURNER_SECTOR_SIZE = 512\n\n/**\n * CFB mini-stream sector size in bytes (64).\n */\nexport const MSG_BURNER_MINI_SECTOR_SIZE = 64\n\n/**\n * Threshold below which streams are stored in the mini-stream (4096).\n */\nexport const MSG_BURNER_MINI_STREAM_CUTOFF = 4096\n\n/**\n * Number of 32-bit integers per standard sector (128).\n */\nexport const MSG_BURNER_INTS_PER_SECTOR = MSG_BURNER_SECTOR_SIZE / 4\n\n/**\n * Maximum DIFAT entries stored in the CFB header (109).\n */\nexport const MSG_BURNER_DIFAT_HEADER_SLOTS = 109\n\n/**\n * CFB directory entry size in bytes (128).\n */\nexport const MSG_BURNER_DIR_ENTRY_SIZE = 128\n\n/**\n * FAT sector marker: this sector holds FAT data (-3).\n */\nexport const MSG_BURNER_FAT_SECTOR_MARKER = -3\n\n/**\n * DIFAT sector marker: this sector holds DIFAT data (-4).\n */\nexport const MSG_BURNER_DIFAT_SECTOR_MARKER = -4\n\n/**\n * Maximum UTF-16 code units allowed in a CFB directory entry name (31).\n * The fixed 64-byte name field holds 32 UTF-16 units including the\n * NUL terminator, so the name itself is capped at 31 units.\n */\nexport const MSG_BURNER_NAME_MAX = 31\n\n/**\n * Root entry CLSID for MSG compound files.\n */\nexport const MSG_BURNER_ROOT_CLSID = new Uint8Array([\n\t0x0b, 0x0d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,\n])\n\n// === EmailParser\n\n/**\n * File extensions recognized as RFC 2822 / MIME email files.\n */\nexport const EML_EXTENSIONS: readonly string[] = ['.eml']\n\n/**\n * File extensions recognized as Outlook binary email files.\n */\nexport const MSG_EXTENSIONS: readonly string[] = ['.msg']\n\n/**\n * MIME types recognized as RFC 2822 / MIME email files.\n */\nexport const EML_MIME_TYPES: readonly string[] = ['message/rfc822']\n\n/**\n * MIME types recognized as Outlook binary email files.\n */\nexport const MSG_MIME_TYPES: readonly string[] = ['application/vnd.ms-outlook']\n\n/**\n * Default charset for decoding MIME part bodies.\n */\nexport const FALLBACK_CHARSET = 'utf-8'\n\n/**\n * Default file name for attachments without an explicit name.\n */\nexport const FALLBACK_ATTACHMENT_NAME = 'attachment'\n\n/**\n * Common MIME types to file extensions mapping.\n * Used for inferring the correct extension during file extraction.\n */\nexport const MIME_EXTENSIONS: ReadonlyMap<string, string> = new Map([\n\t['image/jpeg', '.jpg'],\n\t['image/jpg', '.jpg'],\n\t['image/png', '.png'],\n\t['image/gif', '.gif'],\n\t['image/webp', '.webp'],\n\t['application/pdf', '.pdf'],\n\t['text/plain', '.txt'],\n\t['text/csv', '.csv'],\n\t['text/html', '.html'],\n\t['application/json', '.json'],\n\t['application/zip', '.zip'],\n\t['application/vnd.ms-excel', '.xls'],\n\t['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', '.xlsx'],\n\t['application/msword', '.doc'],\n\t['application/vnd.openxmlformats-officedocument.wordprocessingml.document', '.docx'],\n\t['application/vnd.ms-powerpoint', '.ppt'],\n\t['application/vnd.openxmlformats-officedocument.presentationml.presentation', '.pptx'],\n\t['message/rfc822', '.eml'],\n\t['application/vnd.ms-outlook', '.msg'],\n])\n\n/**\n * Maximum multipart nesting depth accepted by `parseMIMEPart`.\n * Guards against pathological or hostile MIME trees causing\n * unbounded recursion.\n */\nexport const MIME_MAX_DEPTH = 50\n\n/**\n * Minimum valid code point for each UTF-8 sequence length, keyed by the\n * number of continuation bytes (1, 2, or 3). Enforces the WHATWG\n * requirement that a sequence encode the shortest possible form — an\n * overlong encoding (a code point below its sequence's minimum) is\n * rejected rather than accepted by `decodeUTF8`.\n */\nexport const UTF8_SEQUENCE_MINIMUM: Readonly<Record<number, number>> = {\n\t1: 0x80,\n\t2: 0x800,\n\t3: 0x10000,\n}\n\n/**\n * Windows-1252 high-byte (0x80-0x9F) to Unicode code point lookup.\n * Index `n` maps byte `0x80 + n` to its Unicode code point; entries\n * that Windows-1252 leaves undefined map to the byte's own value\n * (C1 control code passthrough) per the WHATWG encoding standard.\n */\nexport const WINDOWS_1252_HIGH: readonly number[] = [\n\t0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039,\n\t0x0152, 0x008d, 0x017d, 0x008f, 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,\n\t0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,\n]\n","import type { MSGErrorCode } from './types.js'\n\n// AGENTS §12: an MSG/EML parsing or burning failure `throw`s an `MSGError`\n// carrying a machine-readable `code`, so a `catch` branches on `error.code`\n// instead of parsing the message. `EmailParserInterface.parse` instead\n// surfaces the same `MSGError` through a `Result<EmailChain, MSGError>`\n// so a malformed file never throws across that boundary.\n\n/**\n * An error thrown or returned by the MSG/EML parsing and burning surfaces.\n *\n * @remarks\n * Carries a machine-readable {@link MSGErrorCode} so a `catch` (or a\n * `Failure.error` branch) can dispatch on `error.code` instead of parsing\n * the message text. `context` carries whatever structured detail the\n * throwing site has on hand (e.g. `{ offset, expected }`).\n */\nexport class MSGError extends Error {\n\treadonly code: MSGErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\tconstructor(code: MSGErrorCode, message: string, context?: Readonly<Record<string, unknown>>) {\n\t\tsuper(message)\n\t\tthis.name = 'MSGError'\n\t\tthis.code = code\n\t\tthis.context = context\n\t}\n}\n\n/**\n * Narrow an unknown caught (or `Failure.error`) value to an {@link MSGError}.\n *\n * @param value - The value to test (typically a `catch` binding or a `Result.error`)\n * @returns `true` when `value` is an {@link MSGError}\n *\n * @example\n * ```ts\n * import { isMSGError } from '@src/core'\n *\n * try {\n * \treader.parse()\n * } catch (error) {\n * \tif (isMSGError(error) && error.code === 'MALFORMED') return\n * }\n * ```\n */\nexport function isMSGError(value: unknown): value is MSGError {\n\treturn value instanceof MSGError\n}\n","import type {\n\tResult,\n\tSuccess,\n\tFailure,\n\tEmailFormat,\n\tMIMEHeader,\n\tMIMEPart,\n\tEmailAttachment,\n\tEmailMessage,\n\tMSGEncoding,\n\tMSGReaderInterface,\n} from './types.js'\nimport { MSGError } from './errors.js'\nimport {\n\tMIME_EXTENSIONS,\n\tMIME_MAX_DEPTH,\n\tWINDOWS_1252_HIGH,\n\tUTF8_SEQUENCE_MINIMUM,\n} from './constants.js'\n\n// === Result Helpers\n\n/**\n * Construct a {@link Success} wrapping a value.\n *\n * @param value - The value to wrap\n * @returns A `Success<T>` result\n *\n * @example\n * ```ts\n * const result = success(42) // { success: true, value: 42 }\n * ```\n */\nexport function success<T>(value: T): Success<T> {\n\treturn { success: true, value }\n}\n\n/**\n * Construct a {@link Failure} wrapping an error.\n *\n * @param error - The error to wrap\n * @returns A `Failure<E>` result\n *\n * @example\n * ```ts\n * const result = failure(new MSGError('MALFORMED', 'bad input'))\n * ```\n */\nexport function failure<E>(error: E): Failure<E> {\n\treturn { success: false, error }\n}\n\n/**\n * Narrow a Result to Success.\n *\n * @param result - Result to check\n * @returns True when result is Success\n */\nexport function isSuccess<T, E>(result: Result<T, E>): result is Success<T> {\n\treturn result.success\n}\n\n/**\n * Narrow a Result to Failure.\n *\n * @param result - Result to check\n * @returns True when result is Failure\n */\nexport function isFailure<T, E>(result: Result<T, E>): result is Failure<E> {\n\treturn !result.success\n}\n\n/**\n * Narrow an unknown value to a plain record.\n *\n * @param value - Value to check\n * @returns True when value is a non-null, non-array object\n */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n// === MSG Helpers\n\n/**\n * Validate that a DataView starts with the CFB magic header.\n *\n * @param view - DataView to check\n * @returns True when the first 8 bytes match the CFB signature\n */\nexport function isMSGFile(view: DataView): boolean {\n\tconst header = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1]\n\tif (view.byteLength < header.length) return false\n\tfor (let i = 0; i < header.length; i++) {\n\t\tif (view.getUint8(i) !== header[i]) return false\n\t}\n\treturn true\n}\n\n/**\n * Remove trailing null characters from a string.\n *\n * @param text - Input string\n * @returns String with trailing nulls removed\n */\nexport function removeTrailingNull(text: string): string {\n\tconst index = text.indexOf('\\0')\n\tif (index !== -1) {\n\t\treturn text.substring(0, index)\n\t}\n\treturn text\n}\n\n/**\n * Read a UTF-16LE string from a DataView.\n *\n * @param view - DataView to read from\n * @param offset - Byte offset to start reading\n * @param charCount - Number of UTF-16 code units to read\n * @returns Decoded string\n * @throws {@link MSGError} with code `MALFORMED` when the requested range\n * exceeds the view's bounds\n */\nexport function readUTF16String(view: DataView, offset: number, charCount: number): string {\n\tconst end = offset + charCount * 2\n\tif (offset < 0 || charCount < 0 || end > view.byteLength) {\n\t\tthrow new MSGError('MALFORMED', 'UTF-16 string range exceeds view bounds', {\n\t\t\toffset,\n\t\t\tcharCount,\n\t\t\tbyteLength: view.byteLength,\n\t\t})\n\t}\n\tlet result = ''\n\tfor (let i = 0; i < charCount; i++) {\n\t\tconst code = view.getUint16(offset + i * 2, true)\n\t\tresult += String.fromCharCode(code)\n\t}\n\treturn result\n}\n\n/**\n * Read a non-Unicode (PT_STRING8) string from a byte array using a\n * pure-ES decoder — no `TextDecoder` dependency, so this stays usable\n * in the core's DOM/Node-free environment.\n *\n * @param data - Binary data\n * @param encoding - Encoding to decode with (default `'windows-1252'`)\n * @returns Decoded string\n *\n * @example\n * ```ts\n * readANSIString(new Uint8Array([0x93, 0x41, 0x94])) // '“A”'\n * ```\n */\nexport function readANSIString(data: Uint8Array, encoding?: MSGEncoding): string {\n\tconst resolved = encoding ?? 'windows-1252'\n\tif (resolved === 'utf-16le') {\n\t\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength)\n\t\treturn readUTF16String(view, 0, Math.floor(data.length / 2))\n\t}\n\tif (resolved === 'utf-8') return decodeUTF8(data)\n\tif (resolved === 'latin1') return decodeLatin1(data)\n\treturn decodeWindows1252(data)\n}\n\n/**\n * Convert a Windows FILETIME (100-ns intervals since 1601-01-01) to a UTC date string.\n * Combines the low/high 32-bit halves with `BigInt` so the 64-bit interval\n * count never loses precision to float64 rounding.\n *\n * @param low - Low 32 bits of FILETIME\n * @param high - High 32 bits of FILETIME\n * @returns UTC date string\n */\nexport function fileTimeToUTCString(low: number, high: number): string {\n\tconst fileTime = BigInt(low >>> 0) + (BigInt(high >>> 0) << 32n)\n\tconst unixMs = (fileTime - 116444736000000000n) / 10000n\n\treturn new Date(Number(unixMs)).toUTCString()\n}\n\n/**\n * Convert a number to a lowercase hex string with specified padding.\n *\n * @param value - Number to convert\n * @param length - Minimum hex string length (zero-padded)\n * @returns Lowercase hex string\n */\nexport function toHexLower(value: number, length: number): string {\n\tconst hex = '0123456789abcdef'\n\tlet result = ''\n\tlet remaining = value >>> 0\n\tfor (let i = 0; i < length; i++) {\n\t\tresult = hex[remaining & 15] + result\n\t\tremaining = remaining >>> 4\n\t}\n\treturn result\n}\n\n/**\n * Stringify a mixed-endian Microsoft UUID from a byte array.\n *\n * @param data - Byte array containing the UUID\n * @param offset - Byte offset to start reading\n * @returns UUID string in lowercase\n */\nexport function msftUUIDStringify(data: Uint8Array, offset: number): string {\n\tconst hex = '0123456789abcdef'\n\tconst b = (i: number) => hex[(data[offset + i] >> 4) & 15] + hex[data[offset + i] & 15]\n\treturn (\n\t\tb(3) +\n\t\tb(2) +\n\t\tb(1) +\n\t\tb(0) +\n\t\t'-' +\n\t\tb(5) +\n\t\tb(4) +\n\t\t'-' +\n\t\tb(7) +\n\t\tb(6) +\n\t\t'-' +\n\t\tb(8) +\n\t\tb(9) +\n\t\t'-' +\n\t\tb(10) +\n\t\tb(11) +\n\t\tb(12) +\n\t\tb(13) +\n\t\tb(14) +\n\t\tb(15)\n\t)\n}\n\n// === MSGBurner Helpers\n\n/**\n * Round a value up to the nearest multiple of a boundary.\n *\n * @param value - Number to round\n * @param boundary - Must be a power of 2\n * @returns Rounded value\n */\nexport function roundUpToMultiple(value: number, boundary: number): number {\n\treturn (value + boundary - 1) & ~(boundary - 1)\n}\n\n/**\n * Compute how many sectors are needed to hold a given byte count.\n *\n * @param bytes - Total byte count\n * @param sectorSize - Sector size in bytes\n * @returns Number of sectors (0 when bytes ≤ 0)\n */\nexport function sectorsNeeded(bytes: number, sectorSize: number): number {\n\tif (bytes <= 0) return 0\n\treturn roundUpToMultiple(bytes, sectorSize) / sectorSize\n}\n\n/**\n * CFB-compliant directory name comparator.\n * Compares by UTF-16 length first, then by uppercased code points.\n *\n * @param a - First name\n * @param b - Second name\n * @returns Negative, zero, or positive\n */\nexport function compareCFBName(a: string, b: string): number {\n\tconst diff = a.length - b.length\n\tif (diff !== 0) return diff\n\tconst x = a.toUpperCase()\n\tconst y = b.toUpperCase()\n\tif (x > y) return 1\n\tif (x < y) return -1\n\treturn 0\n}\n\n// === Pure-ES Encoding Decoders\n\n/**\n * Decode a Base64 string into raw bytes without relying on `atob`.\n * Ignores ASCII whitespace and tolerates missing padding.\n *\n * @param text - Base64-encoded string\n * @returns Decoded byte array\n * @throws {@link MSGError} with code `MALFORMED` when the string contains\n * a character outside the Base64 alphabet\n *\n * @example\n * ```ts\n * decodeBase64('SGVsbG8=') // Uint8Array [72, 101, 108, 108, 111]\n * ```\n */\nexport function decodeBase64(text: string): Uint8Array {\n\tconst alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n\tconst cleaned = text.replace(/[ \\t\\n\\r\\f\\v]+/g, '').replace(/=+$/, '')\n\tconst bytes: number[] = []\n\tlet buffer = 0\n\tlet bits = 0\n\n\tfor (const char of cleaned) {\n\t\tconst index = alphabet.indexOf(char)\n\t\tif (index === -1) {\n\t\t\tthrow new MSGError('MALFORMED', `Invalid Base64 character: ${char}`, { char })\n\t\t}\n\t\tbuffer = (buffer << 6) | index\n\t\tbits += 6\n\t\tif (bits >= 8) {\n\t\t\tbits -= 8\n\t\t\tbytes.push((buffer >> bits) & 0xff)\n\t\t}\n\t}\n\n\treturn new Uint8Array(bytes)\n}\n\n/**\n * Encode a string into UTF-8 bytes, handling surrogate pairs.\n * A lone (unpaired) surrogate encodes as U+FFFD.\n *\n * @param text - String to encode\n * @returns UTF-8 byte array\n *\n * @example\n * ```ts\n * encodeUTF8('A') // Uint8Array [65]\n * ```\n */\nexport function encodeUTF8(text: string): Uint8Array {\n\tconst bytes: number[] = []\n\n\tfor (let i = 0; i < text.length; i++) {\n\t\tlet code = text.charCodeAt(i)\n\n\t\tif (code >= 0xd800 && code <= 0xdbff) {\n\t\t\tconst next = text.charCodeAt(i + 1)\n\t\t\tif (next >= 0xdc00 && next <= 0xdfff) {\n\t\t\t\tcode = (code - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000\n\t\t\t\ti++\n\t\t\t} else {\n\t\t\t\tcode = 0xfffd\n\t\t\t}\n\t\t} else if (code >= 0xdc00 && code <= 0xdfff) {\n\t\t\tcode = 0xfffd\n\t\t}\n\n\t\tif (code < 0x80) {\n\t\t\tbytes.push(code)\n\t\t} else if (code < 0x800) {\n\t\t\tbytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f))\n\t\t} else if (code < 0x10000) {\n\t\t\tbytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f))\n\t\t} else {\n\t\t\tbytes.push(\n\t\t\t\t0xf0 | (code >> 18),\n\t\t\t\t0x80 | ((code >> 12) & 0x3f),\n\t\t\t\t0x80 | ((code >> 6) & 0x3f),\n\t\t\t\t0x80 | (code & 0x3f),\n\t\t\t)\n\t\t}\n\t}\n\n\treturn new Uint8Array(bytes)\n}\n\n/**\n * Decode UTF-8 bytes into a string, WHATWG-style: an invalid byte\n * sequence decodes as U+FFFD rather than throwing. Rejects overlong\n * encodings, surrogate code points (0xD800-0xDFFF), and code points\n * beyond 0x10FFFF — each invalid sequence yields exactly one U+FFFD\n * and decoding resumes at the next lead byte.\n *\n * @param bytes - UTF-8 byte array\n * @returns Decoded string\n *\n * @example\n * ```ts\n * decodeUTF8(new Uint8Array([65])) // 'A'\n * decodeUTF8(new Uint8Array([0xff])) // '�'\n * ```\n */\nexport function decodeUTF8(bytes: Uint8Array): string {\n\tlet result = ''\n\tlet i = 0\n\n\twhile (i < bytes.length) {\n\t\tconst byte0 = bytes[i]\n\n\t\tif (byte0 < 0x80) {\n\t\t\tresult += String.fromCharCode(byte0)\n\t\t\ti++\n\t\t\tcontinue\n\t\t}\n\n\t\tlet length = 0\n\t\tlet codePoint = 0\n\t\tif ((byte0 & 0xe0) === 0xc0) {\n\t\t\tlength = 1\n\t\t\tcodePoint = byte0 & 0x1f\n\t\t} else if ((byte0 & 0xf0) === 0xe0) {\n\t\t\tlength = 2\n\t\t\tcodePoint = byte0 & 0x0f\n\t\t} else if ((byte0 & 0xf8) === 0xf0) {\n\t\t\tlength = 3\n\t\t\tcodePoint = byte0 & 0x07\n\t\t} else {\n\t\t\tresult += '�'\n\t\t\ti++\n\t\t\tcontinue\n\t\t}\n\n\t\tif (i + length >= bytes.length) {\n\t\t\tresult += '�'\n\t\t\ti++\n\t\t\tcontinue\n\t\t}\n\n\t\tlet valid = true\n\t\tlet value = codePoint\n\t\tfor (let j = 1; j <= length; j++) {\n\t\t\tconst next = bytes[i + j]\n\t\t\tif ((next & 0xc0) !== 0x80) {\n\t\t\t\tvalid = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tvalue = (value << 6) | (next & 0x3f)\n\t\t}\n\n\t\tif (!valid) {\n\t\t\tresult += '�'\n\t\t\ti++\n\t\t\tcontinue\n\t\t}\n\n\t\tconst minimum = UTF8_SEQUENCE_MINIMUM[length]\n\t\tconst isOverlong = minimum !== undefined && value < minimum\n\t\tconst isSurrogate = value >= 0xd800 && value <= 0xdfff\n\t\tconst isOutOfRange = value > 0x10ffff\n\n\t\tif (isOverlong || isSurrogate || isOutOfRange) {\n\t\t\tresult += '�'\n\t\t\ti += length + 1\n\t\t\tcontinue\n\t\t}\n\n\t\ti += length + 1\n\n\t\tif (value >= 0x10000) {\n\t\t\tvalue -= 0x10000\n\t\t\tresult += String.fromCharCode(0xd800 + (value >> 10), 0xdc00 + (value & 0x3ff))\n\t\t} else {\n\t\t\tresult += String.fromCharCode(value)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Decode Latin-1 (ISO-8859-1) bytes into a string, byte-for-code-point.\n *\n * @param bytes - Latin-1 byte array\n * @returns Decoded string\n *\n * @example\n * ```ts\n * decodeLatin1(new Uint8Array([0xe9])) // 'é'\n * ```\n */\nexport function decodeLatin1(bytes: Uint8Array): string {\n\tlet result = ''\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tresult += String.fromCharCode(bytes[i])\n\t}\n\treturn result\n}\n\n/**\n * Decode Windows-1252 bytes into a string. Identical to {@link decodeLatin1}\n * except for the 0x80-0x9F range, which maps through {@link WINDOWS_1252_HIGH}.\n *\n * @param bytes - Windows-1252 byte array\n * @returns Decoded string\n *\n * @example\n * ```ts\n * decodeWindows1252(new Uint8Array([0x93])) // '“'\n * ```\n */\nexport function decodeWindows1252(bytes: Uint8Array): string {\n\tlet result = ''\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tconst byte = bytes[i]\n\t\tif (byte >= 0x80 && byte <= 0x9f) {\n\t\t\tresult += String.fromCodePoint(WINDOWS_1252_HIGH[byte - 0x80])\n\t\t} else {\n\t\t\tresult += String.fromCharCode(byte)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Resolve a free-form charset label (as seen in a MIME `charset` parameter)\n * to a supported {@link MSGEncoding}. Unknown or absent labels fall back\n * to `'utf-8'`.\n *\n * @param label - Charset label to resolve (case-insensitive)\n * @returns Resolved encoding\n *\n * @example\n * ```ts\n * resolveEncoding('ISO-8859-1') // 'latin1'\n * resolveEncoding(undefined) // 'utf-8'\n * ```\n */\nexport function resolveEncoding(label: string | undefined): MSGEncoding {\n\tconst lower = label?.trim().toLowerCase()\n\tif (lower === 'utf-8' || lower === 'utf8') return 'utf-8'\n\tif (lower === 'utf-16le' || lower === 'utf-16') return 'utf-16le'\n\tif (lower === 'windows-1252' || lower === 'cp1252') return 'windows-1252'\n\tif (\n\t\tlower === 'us-ascii' ||\n\t\tlower === 'ascii' ||\n\t\tlower === 'iso-8859-1' ||\n\t\tlower === 'iso8859-1' ||\n\t\tlower === 'latin1'\n\t) {\n\t\treturn 'latin1'\n\t}\n\treturn 'utf-8'\n}\n\n// === EmailParser Helpers\n\n/**\n * Narrow an unknown value to a valid EmailFormat.\n *\n * @param value - Value to check\n * @returns True when value is 'eml' or 'msg'\n */\nexport function isEmailFormat(value: unknown): value is EmailFormat {\n\treturn value === 'eml' || value === 'msg'\n}\n\n/**\n * Derive the EmailFormat from a file name and/or MIME type.\n * Returns undefined when the format cannot be determined.\n *\n * @param name - File name to inspect\n * @param mime - MIME type to inspect\n * @returns Detected format or undefined\n *\n * @example\n * ```ts\n * detectFormat('message.eml', undefined) // 'eml'\n * detectFormat(undefined, 'application/vnd.ms-outlook') // 'msg'\n * ```\n */\nexport function detectFormat(\n\tname: string | undefined,\n\tmime: string | undefined,\n): EmailFormat | undefined {\n\tconst lower = name?.toLowerCase()\n\n\tif (lower?.endsWith('.eml') === true) return 'eml'\n\tif (lower?.endsWith('.msg') === true) return 'msg'\n\n\tif (mime === 'message/rfc822') return 'eml'\n\tif (mime === 'application/vnd.ms-outlook') return 'msg'\n\n\treturn undefined\n}\n\n/**\n * Parse headers from a raw RFC 2822 / MIME header text block.\n *\n * @param text - Raw header text\n * @returns Map of parsed header objects\n */\nexport function parseMIMEHeaders(text: string): ReadonlyMap<string, MIMEHeader> {\n\tconst raw: Array<{ name: string; value: string }> = []\n\n\tfor (const line of text.split('\\n')) {\n\t\tif (line === '') continue\n\t\tif ((line.startsWith(' ') || line.startsWith('\\t')) && raw.length > 0) {\n\t\t\tconst last = raw[raw.length - 1]\n\t\t\tif (last !== undefined) {\n\t\t\t\traw[raw.length - 1] = { name: last.name, value: last.value + ' ' + line.trim() }\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tconst colon = line.indexOf(':')\n\t\tif (colon === -1) continue\n\t\traw.push({\n\t\t\tname: line.slice(0, colon).trim().toLowerCase(),\n\t\t\tvalue: line.slice(colon + 1).trim(),\n\t\t})\n\t}\n\n\tconst map = new Map<string, MIMEHeader>()\n\tfor (const { name, value } of raw) {\n\t\tif (!map.has(name)) {\n\t\t\tconst segments = value.split(';')\n\t\t\tconst val = (segments[0] ?? '').trim()\n\t\t\tconst params = new Map<string, string>()\n\n\t\t\tfor (let i = 1; i < segments.length; i++) {\n\t\t\t\tconst segment = (segments[i] ?? '').trim()\n\t\t\t\tconst eq = segment.indexOf('=')\n\t\t\t\tif (eq === -1) continue\n\t\t\t\tconst k = segment.slice(0, eq).trim().toLowerCase()\n\t\t\t\tlet v = segment.slice(eq + 1).trim()\n\t\t\t\tif (v.startsWith('\"') && v.endsWith('\"')) v = v.slice(1, -1)\n\t\t\t\tparams.set(k, v)\n\t\t\t}\n\n\t\t\tmap.set(name, { value: val, params })\n\t\t}\n\t}\n\treturn map\n}\n\n/**\n * Parse a raw RFC 2822 / MIME text string into a MIMEPart tree.\n * Line endings are normalised to \\n before processing. Recursion is\n * capped at {@link MIME_MAX_DEPTH} to guard against a hostile or\n * pathological multipart nesting cycle.\n *\n * @param raw - Raw MIME text\n * @param depth - Current recursion depth (internal; callers omit this)\n * @returns Parsed MIMEPart tree\n * @throws {@link MSGError} with code `CYCLE` when nesting exceeds {@link MIME_MAX_DEPTH}\n */\nexport function parseMIMEPart(raw: string, depth = 0): MIMEPart {\n\tif (depth > MIME_MAX_DEPTH) {\n\t\tthrow new MSGError('CYCLE', 'MIME multipart nesting exceeds maximum depth', {\n\t\t\tdepth,\n\t\t\tmax: MIME_MAX_DEPTH,\n\t\t})\n\t}\n\n\tconst normalised = raw.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n\tconst split = normalised.indexOf('\\n\\n')\n\tconst headerText = split === -1 ? normalised : normalised.slice(0, split)\n\tconst body = split === -1 ? '' : normalised.slice(split + 2)\n\n\tconst headers = parseMIMEHeaders(headerText)\n\tconst contentType = headers.get('content-type')\n\tconst primaryType = (contentType?.value ?? '').split(';')[0].trim().toLowerCase()\n\tconst boundary = contentType?.params.get('boundary') ?? ''\n\n\tconst parts: MIMEPart[] = []\n\tif (primaryType.startsWith('multipart/') && boundary !== '') {\n\t\tconst delimiter = '--' + boundary\n\t\tconst lines = body.split('\\n')\n\t\tlet current: string[] = []\n\t\tlet inside = false\n\n\t\tfor (const line of lines) {\n\t\t\tconst trimmed = line.trimEnd()\n\t\t\tif (trimmed === delimiter + '--') {\n\t\t\t\tif (inside && current.length > 0) parts.push(parseMIMEPart(current.join('\\n'), depth + 1))\n\t\t\t\tinside = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (trimmed === delimiter) {\n\t\t\t\tif (inside && current.length > 0) parts.push(parseMIMEPart(current.join('\\n'), depth + 1))\n\t\t\t\tcurrent = []\n\t\t\t\tinside = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (inside) current.push(line)\n\t\t}\n\n\t\tif (inside && current.length > 0) parts.push(parseMIMEPart(current.join('\\n'), depth + 1))\n\t}\n\n\treturn { headers, body, parts }\n}\n\n/**\n * Decode a MIME-encoded body string into a raw byte array.\n *\n * @param body - Raw encoded string\n * @param encoding - Encoding type (e.g., 'base64', 'quoted-printable')\n * @returns Decoded byte array\n * @throws {@link MSGError} with code `MALFORMED` when `encoding` is `'base64'`\n * and `body` contains an invalid Base64 character\n */\nexport function decodeMIMEEncoding(body: string, encoding: string): Uint8Array {\n\tconst enc = encoding.toLowerCase()\n\n\tif (enc === 'base64') {\n\t\treturn decodeBase64(body)\n\t}\n\n\tif (enc === 'quoted-printable') {\n\t\tconst unwrapped = body.replace(/=\\r?\\n/g, '')\n\t\tconst result: number[] = []\n\t\tlet i = 0\n\n\t\twhile (i < unwrapped.length) {\n\t\t\tif (unwrapped[i] === '=' && i + 2 < unwrapped.length) {\n\t\t\t\tconst hex = unwrapped.slice(i + 1, i + 3)\n\t\t\t\tif (/^[0-9A-Fa-f]{2}$/.test(hex)) {\n\t\t\t\t\tresult.push(parseInt(hex, 16))\n\t\t\t\t\ti += 3\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tresult.push(unwrapped.charCodeAt(i))\n\t\t\ti++\n\t\t}\n\n\t\treturn new Uint8Array(result)\n\t}\n\n\treturn encodeUTF8(body)\n}\n\n/**\n * Decode a MIME-encoded body into a text string based on an arbitrary\n * charset label, resolved via {@link resolveEncoding}.\n *\n * @param body - Raw encoded string\n * @param encoding - Transfer encoding type\n * @param charset - Character set label (e.g., 'utf-8')\n * @returns Decoded string\n */\nexport function decodeMIMEText(body: string, encoding: string, charset: string): string {\n\tconst enc = encoding.toLowerCase()\n\tif (enc !== 'base64' && enc !== 'quoted-printable') {\n\t\treturn body // Return directly for 7bit/8bit text\n\t}\n\tconst bytes = decodeMIMEEncoding(body, encoding)\n\treturn readANSIString(bytes, resolveEncoding(charset))\n}\n\n/**\n * Decode RFC 2047 encoded words in header values.\n * Handles both Base64 (B) and Quoted-Printable (Q) forms.\n *\n * @param text - Header value string potentially containing encoded words\n * @returns Decoded string\n *\n * @example\n * ```ts\n * decodeMIMEWords('=?UTF-8?B?SGVsbG8=?=') // 'Hello'\n * ```\n */\nexport function decodeMIMEWords(text: string): string {\n\t// RFC 2047 6.2: linear whitespace between two adjacent encoded-words is\n\t// part of the encoding, not content — drop it before decoding.\n\tconst collapsed = text.replace(\n\t\t/(=\\?[^?]+\\?[BbQq]\\?[^?]*\\?=)[ \\t\\r\\n]+(?==\\?[^?]+\\?[BbQq]\\?[^?]*\\?=)/g,\n\t\t'$1',\n\t)\n\treturn collapsed.replace(\n\t\t/=\\?([^?]+)\\?([BbQq])\\?([^?]*)\\?=/g,\n\t\t(_match, charset: string, enc: string, encoded: string) => {\n\t\t\ttry {\n\t\t\t\tconst upper = enc.toUpperCase()\n\t\t\t\tconst bytes =\n\t\t\t\t\tupper === 'B'\n\t\t\t\t\t\t? decodeMIMEEncoding(encoded, 'base64')\n\t\t\t\t\t\t: decodeMIMEEncoding(encoded.replace(/_/g, ' '), 'quoted-printable')\n\t\t\t\treturn readANSIString(bytes, resolveEncoding(charset))\n\t\t\t} catch {\n\t\t\t\treturn encoded\n\t\t\t}\n\t\t},\n\t)\n}\n\n/**\n * Format a name and email into a standard composite address.\n *\n * @param name - Display name\n * @param email - Email address\n * @returns Formatted address string\n */\nexport function formatEmailAddress(name: string | undefined, email: string | undefined): string {\n\tconst n = name?.trim() ?? ''\n\tconst e = email?.trim() ?? ''\n\tif (n.length > 0 && e.length > 0) return `${n} <${e}>`\n\tif (n.length > 0) return n\n\treturn e\n}\n\n/**\n * Extract a single EmailMessage from a parsed MSGReader.\n * Reads field data and attachments from the reader interface.\n *\n * Each attachment is read independently: a corrupt attachment throws\n * from `reader.attachment(i)` is caught and that attachment is skipped\n * so the rest of the message still parses. This containment keeps one\n * damaged attachment stream from failing the entire message extraction.\n *\n * @param reader - A parsed MSGReaderInterface instance\n * @returns Structured EmailMessage\n */\nexport function extractMessageFromMSG(reader: MSGReaderInterface): EmailMessage {\n\tconst data = reader.parse()\n\n\tconst from = formatEmailAddress(data.senderName, data.senderSMTPAddress ?? data.senderEmail)\n\n\tconst recipients = data.recipients ?? []\n\tconst to = recipients\n\t\t.filter((r) => r.recipientRole === 'to')\n\t\t.map((r) => formatEmailAddress(r.name, r.smtpAddress ?? r.email))\n\t\t.filter((s) => s.length > 0)\n\tconst cc = recipients\n\t\t.filter((r) => r.recipientRole === 'cc')\n\t\t.map((r) => formatEmailAddress(r.name, r.smtpAddress ?? r.email))\n\t\t.filter((s) => s.length > 0)\n\n\tconst rawDate = data.messageDeliveryTime ?? data.clientSubmitTime\n\tlet date: Date | undefined\n\tif (rawDate !== undefined) {\n\t\tconst parsed = new Date(rawDate)\n\t\tdate = isNaN(parsed.getTime()) ? undefined : parsed\n\t}\n\n\tconst attachments: EmailAttachment[] = []\n\tconst attachmentFields = data.attachments ?? []\n\tfor (let i = 0; i < attachmentFields.length; i++) {\n\t\tconst attachment = attachmentFields[i]\n\t\tif (attachment === undefined) continue\n\t\tif (attachment.attachmentHidden === true) continue\n\t\tif (attachment.innerMSGContent === true) continue\n\t\ttry {\n\t\t\tconst extracted = reader.attachment(i)\n\t\t\tattachments.push({\n\t\t\t\tname: extracted.fileName,\n\t\t\t\tmimeType: attachment.mimeType ?? 'application/octet-stream',\n\t\t\t\tsize: extracted.content.length,\n\t\t\t\tbytes: extracted.content,\n\t\t\t})\n\t\t} catch {\n\t\t\t// A single corrupt attachment stream must not fail the whole message.\n\t\t\tcontinue\n\t\t}\n\t}\n\n\treturn {\n\t\tfrom,\n\t\tto,\n\t\tcc,\n\t\tsubject: data.subject ?? '',\n\t\tdate,\n\t\ttext: data.body ?? '',\n\t\thtml: data.bodyHTML ?? '',\n\t\tattachments,\n\t}\n}\n\n/**\n * Extract a single EmailMessage from a top-level MIMEPart.\n * Walks the full MIME tree to collect text, HTML, and attachments.\n *\n * @param part - Root MIMEPart from parseMIMEPart\n * @returns Structured EmailMessage\n */\nexport function extractMessage(part: MIMEPart): EmailMessage {\n\tconst headerValue = (name: string): string => decodeMIMEWords(part.headers.get(name)?.value ?? '')\n\n\tconst splitAddresses = (raw: string): readonly string[] =>\n\t\traw.length === 0\n\t\t\t? []\n\t\t\t: raw\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t.filter((s) => s.length > 0)\n\n\tconst rawDate = part.headers.get('date')?.value\n\tlet date: Date | undefined\n\tif (rawDate !== undefined) {\n\t\tconst parsed = new Date(rawDate)\n\t\tdate = isNaN(parsed.getTime()) ? undefined : parsed\n\t}\n\n\tconst collectedText: string[] = []\n\tconst collectedHTML: string[] = []\n\tconst attachments: EmailAttachment[] = []\n\n\tconst walk = (p: MIMEPart) => {\n\t\tconst contentType = p.headers.get('content-type')\n\t\tconst disposition = p.headers.get('content-disposition')\n\t\tconst transferEncoding = p.headers.get('content-transfer-encoding')\n\n\t\tconst primaryType = (contentType?.value ?? 'text/plain').split(';')[0].trim().toLowerCase()\n\t\tconst encoding = (transferEncoding?.value ?? '7bit').trim()\n\t\tconst charset = contentType?.params.get('charset') ?? 'utf-8'\n\t\tconst dispositionKind = (disposition?.value ?? '').trim().toLowerCase()\n\n\t\tif (primaryType.startsWith('multipart/')) {\n\t\t\tfor (const child of p.parts) walk(child)\n\t\t\treturn\n\t\t}\n\n\t\tconst isAttachmentPart = dispositionKind === 'attachment'\n\n\t\tif (isAttachmentPart) {\n\t\t\tconst name =\n\t\t\t\tdisposition?.params.get('filename') ?? contentType?.params.get('name') ?? 'attachment'\n\t\t\tconst bytes = decodeMIMEEncoding(p.body, encoding)\n\t\t\tattachments.push({\n\t\t\t\tname: decodeMIMEWords(name),\n\t\t\t\tmimeType: primaryType,\n\t\t\t\tsize: bytes.length,\n\t\t\t\tbytes,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tif (primaryType === 'text/plain') {\n\t\t\tcollectedText.push(decodeMIMEText(p.body, encoding, charset))\n\t\t\treturn\n\t\t}\n\n\t\tif (primaryType === 'text/html') {\n\t\t\tcollectedHTML.push(decodeMIMEText(p.body, encoding, charset))\n\t\t\treturn\n\t\t}\n\n\t\t// Inline binary parts with a filename become attachments\n\t\tconst inlineName = contentType?.params.get('name') ?? disposition?.params.get('filename')\n\t\tif (inlineName !== undefined) {\n\t\t\tconst bytes = decodeMIMEEncoding(p.body, encoding)\n\t\t\tattachments.push({\n\t\t\t\tname: decodeMIMEWords(inlineName),\n\t\t\t\tmimeType: primaryType,\n\t\t\t\tsize: bytes.length,\n\t\t\t\tbytes,\n\t\t\t})\n\t\t}\n\t}\n\n\twalk(part)\n\n\treturn {\n\t\tfrom: headerValue('from'),\n\t\tto: splitAddresses(headerValue('to')),\n\t\tcc: splitAddresses(headerValue('cc')),\n\t\tsubject: headerValue('subject'),\n\t\tdate,\n\t\ttext: collectedText.join(''),\n\t\thtml: collectedHTML.join(''),\n\t\tattachments,\n\t}\n}\n\n// === Attachment Helpers\n\n/**\n * Infers the file extension for an attachment based on its filename or MIME type.\n * Returns the extension including the dot (e.g., '.jpg').\n *\n * @param mimeType - MIME type to infer from\n * @param fileName - File name to infer from\n * @returns Inferred extension, or `.bin` when neither hint resolves\n */\nexport function inferExtension(mimeType?: string, fileName?: string): string {\n\tif (fileName !== undefined) {\n\t\tconst lastDotIndex = fileName.lastIndexOf('.')\n\t\tif (lastDotIndex !== -1 && lastDotIndex < fileName.length - 1) {\n\t\t\tconst ext = fileName.slice(lastDotIndex).toLowerCase()\n\t\t\t// Basic validation: extension should be alphanumeric and reasonably short\n\t\t\tif (/^\\.[a-z0-9]{1,10}$/.test(ext)) {\n\t\t\t\treturn ext\n\t\t\t}\n\t\t}\n\t}\n\n\tif (mimeType !== undefined) {\n\t\tconst normalized = mimeType.split(';')[0]?.trim().toLowerCase()\n\t\tif (normalized !== undefined) {\n\t\t\tconst ext = MIME_EXTENSIONS.get(normalized)\n\t\t\tif (ext !== undefined) return ext\n\t\t}\n\t}\n\n\treturn '.bin'\n}\n","/**\n * MSGBurner\n *\n * Reconstitutes a valid CFB (Compound Binary File) from a flat list\n * of MSGBurnerEntry descriptors. Used to extract embedded .msg\n * attachments as standalone binary files.\n */\n\nimport type { MSGBurnerInterface, MSGBurnerEntry, MSGBurnerLiteEntry } from './types.js'\nimport {\n\tMSG_FILE_HEADER,\n\tMSG_TYPE_DIRECTORY,\n\tMSG_TYPE_DOCUMENT,\n\tMSG_END_OF_CHAIN,\n\tMSG_UNUSED_BLOCK,\n\tMSG_BURNER_SECTOR_SIZE,\n\tMSG_BURNER_MINI_SECTOR_SIZE,\n\tMSG_BURNER_MINI_STREAM_CUTOFF,\n\tMSG_BURNER_INTS_PER_SECTOR,\n\tMSG_BURNER_DIFAT_HEADER_SLOTS,\n\tMSG_BURNER_DIR_ENTRY_SIZE,\n\tMSG_BURNER_FAT_SECTOR_MARKER,\n\tMSG_BURNER_DIFAT_SECTOR_MARKER,\n\tMSG_BURNER_ROOT_CLSID,\n\tMSG_BURNER_NAME_MAX,\n} from './constants.js'\nimport { sectorsNeeded, compareCFBName } from './helpers.js'\nimport { MSGError } from './errors.js'\n\n// === MSGBurner\n\n/**\n * Reconstitutes a valid CFB (Compound Binary File) from a flat list of\n * {@link MSGBurnerEntry} descriptors — root storage at index 0, its\n * children reachable through `children` indices.\n *\n * @remarks\n * Builds a red-black directory tree, allocates FAT/mini-FAT/DIFAT\n * sectors, then writes the header, directory entries, and stream data\n * into a single binary. Used to extract embedded `.msg` attachments as\n * standalone CFB files.\n */\nexport class MSGBurner implements MSGBurnerInterface {\n\t#liteEntries: MSGBurnerLiteEntry[] = []\n\t#fat: number[] = []\n\t#miniFat: number[] = []\n\n\t/**\n\t * Burn a flat list of CFB entries into a valid compound binary file.\n\t *\n\t * @param entries - Flat entry list starting with Root Entry at index 0\n\t * @returns Complete CFB binary as Uint8Array\n\t * @throws {@link MSGError} with code `BURN` when an entry name exceeds\n\t * the {@link MSG_BURNER_NAME_MAX} UTF-16 code unit limit the CFB directory entry format allows\n\t */\n\tburn(entries: readonly MSGBurnerEntry[]): Uint8Array {\n\t\tthis.#liteEntries = entries.map((entry) => ({\n\t\t\tentry,\n\t\t\tleft: -1,\n\t\t\tright: -1,\n\t\t\tchild: -1,\n\t\t\tfirstSector: 0,\n\t\t\tmini: entry.type === MSG_TYPE_DOCUMENT && entry.length < MSG_BURNER_MINI_STREAM_CUTOFF,\n\t\t\tred: false,\n\t\t}))\n\t\tthis.#fat = []\n\t\tthis.#miniFat = []\n\n\t\tthis.#buildTree(0)\n\n\t\t// Allocate directory sectors\n\t\tconst dirSectorCount = sectorsNeeded(\n\t\t\tMSG_BURNER_DIR_ENTRY_SIZE * this.#liteEntries.length,\n\t\t\tMSG_BURNER_SECTOR_SIZE,\n\t\t)\n\t\tconst entriesFirstSector = this.#allocateFat(dirSectorCount)\n\n\t\t// Allocate large document streams\n\t\tfor (let i = 0; i < this.#liteEntries.length; i++) {\n\t\t\tconst le = this.#liteEntries[i]\n\t\t\tif (le.entry.type === MSG_TYPE_DOCUMENT && !le.mini) {\n\t\t\t\tle.firstSector =\n\t\t\t\t\tle.entry.length === 0\n\t\t\t\t\t\t? MSG_END_OF_CHAIN\n\t\t\t\t\t\t: this.#allocateFat(sectorsNeeded(le.entry.length, MSG_BURNER_SECTOR_SIZE))\n\t\t\t}\n\t\t}\n\n\t\t// Allocate mini-stream document streams\n\t\tfor (let i = 0; i < this.#liteEntries.length; i++) {\n\t\t\tconst le = this.#liteEntries[i]\n\t\t\tif (le.entry.type === MSG_TYPE_DOCUMENT && le.mini) {\n\t\t\t\tle.firstSector =\n\t\t\t\t\tle.entry.length === 0\n\t\t\t\t\t\t? MSG_END_OF_CHAIN\n\t\t\t\t\t\t: this.#allocateMiniFat(sectorsNeeded(le.entry.length, MSG_BURNER_MINI_SECTOR_SIZE))\n\t\t\t}\n\t\t}\n\n\t\t// Allocate mini-FAT sectors\n\t\tconst numMiniFatSectors = sectorsNeeded(4 * this.#miniFat.length, MSG_BURNER_SECTOR_SIZE)\n\t\tconst firstMiniFatSector =\n\t\t\tnumMiniFatSectors !== 0 ? this.#allocateFat(numMiniFatSectors) : MSG_END_OF_CHAIN\n\n\t\t// Allocate mini-stream data sectors (root entry body)\n\t\tconst bytesMiniFat = MSG_BURNER_MINI_SECTOR_SIZE * this.#miniFat.length\n\t\tconst firstMiniDataSector =\n\t\t\tbytesMiniFat > 0\n\t\t\t\t? this.#allocateFat(sectorsNeeded(bytesMiniFat, MSG_BURNER_SECTOR_SIZE))\n\t\t\t\t: MSG_END_OF_CHAIN\n\n\t\tthis.#liteEntries[0].firstSector =\n\t\t\tfirstMiniDataSector === MSG_END_OF_CHAIN ? MSG_END_OF_CHAIN : firstMiniDataSector\n\n\t\t// Allocate FAT sectors (self-referencing)\n\t\tconst estimatedFatSectors = Math.max(\n\t\t\t1,\n\t\t\tsectorsNeeded(\n\t\t\t\t4 * (this.#fat.length + Math.ceil(this.#fat.length / MSG_BURNER_INTS_PER_SECTOR) + 1),\n\t\t\t\tMSG_BURNER_SECTOR_SIZE,\n\t\t\t),\n\t\t)\n\t\tconst firstFatSector = this.#allocateFatAs(estimatedFatSectors, MSG_BURNER_FAT_SECTOR_MARKER)\n\t\tconst numFatSectors = this.#fat.length - firstFatSector\n\n\t\t// Allocate DIFAT sectors\n\t\tconst numDifatSectors =\n\t\t\tnumFatSectors > MSG_BURNER_DIFAT_HEADER_SLOTS\n\t\t\t\t? sectorsNeeded(\n\t\t\t\t\t\t4 * Math.ceil(((numFatSectors - MSG_BURNER_DIFAT_HEADER_SLOTS) / 127) * 128),\n\t\t\t\t\t\tMSG_BURNER_SECTOR_SIZE,\n\t\t\t\t\t)\n\t\t\t\t: 0\n\t\tconst firstDifatSector =\n\t\t\tnumDifatSectors !== 0\n\t\t\t\t? this.#allocateFatAs(numDifatSectors, MSG_BURNER_DIFAT_SECTOR_MARKER)\n\t\t\t\t: MSG_END_OF_CHAIN\n\n\t\t// Build the binary\n\t\tconst totalSize = MSG_BURNER_SECTOR_SIZE * (1 + this.#fat.length)\n\t\tconst buffer = new ArrayBuffer(totalSize)\n\t\tconst view = new DataView(buffer)\n\t\tconst bytes = new Uint8Array(buffer)\n\n\t\t// Pad mini-FAT to sector boundary\n\t\twhile (this.#miniFat.length % MSG_BURNER_INTS_PER_SECTOR !== 0) {\n\t\t\tthis.#miniFat.push(MSG_UNUSED_BLOCK)\n\t\t}\n\n\t\t// Build DIFAT arrays\n\t\tconst difat1: number[] = []\n\t\tconst difat2: number[] = []\n\t\tthis.#buildDifat(difat1, difat2, numFatSectors, firstFatSector, firstDifatSector)\n\n\t\tthis.#writeHeader(\n\t\t\tview,\n\t\t\tbytes,\n\t\t\tnumFatSectors,\n\t\t\tentriesFirstSector,\n\t\t\tfirstMiniFatSector,\n\t\t\tnumMiniFatSectors,\n\t\t\tfirstDifatSector,\n\t\t\tnumDifatSectors,\n\t\t\tdifat1,\n\t\t)\n\t\tthis.#writeDirectoryEntries(view, bytes, entriesFirstSector, bytesMiniFat)\n\t\tthis.#writeLargeStreams(bytes)\n\t\tthis.#writeMiniStreams(bytes, firstMiniDataSector)\n\t\tthis.#writeMiniFat(view, firstMiniFatSector)\n\t\tthis.#writeFat(view, firstFatSector)\n\t\tthis.#writeDifat(view, difat2, firstDifatSector, numDifatSectors)\n\n\t\treturn new Uint8Array(buffer)\n\t}\n\n\t// === FAT Allocation\n\n\t#allocateFat(count: number): number {\n\t\tconst first = this.#fat.length\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst next = i + 1 === count ? MSG_END_OF_CHAIN : first + i + 1\n\t\t\tthis.#fat.push(next)\n\t\t}\n\t\treturn first\n\t}\n\n\t#allocateFatAs(count: number, value: number): number {\n\t\tconst first = this.#fat.length\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tthis.#fat.push(value)\n\t\t}\n\t\treturn first\n\t}\n\n\t#allocateMiniFat(count: number): number {\n\t\tconst first = this.#miniFat.length\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst next = i + 1 === count ? MSG_END_OF_CHAIN : first + i + 1\n\t\t\tthis.#miniFat.push(next)\n\t\t}\n\t\treturn first\n\t}\n\n\t// === Red-Black Tree Builder\n\n\t#buildTree(dirIndex: number): void {\n\t\tconst liteEntry = this.#liteEntries[dirIndex]\n\t\tconst children = liteEntry.entry.children\n\t\tif (children === undefined || children.length === 0) return\n\n\t\tconst sorted = children\n\t\t\t.slice()\n\t\t\t.sort((a, b) =>\n\t\t\t\tcompareCFBName(this.#liteEntries[a].entry.name, this.#liteEntries[b].entry.name),\n\t\t\t)\n\n\t\tconst mid = Math.floor(sorted.length / 2)\n\t\tconst rootIndex = sorted[mid]\n\t\tconst rootEntry = this.#liteEntries[rootIndex]\n\t\trootEntry.red = false\n\t\trootEntry.left = this.#splitTree(sorted, 0, mid, true)\n\t\trootEntry.right = this.#splitTree(sorted, mid + 1, sorted.length, true)\n\t\tliteEntry.child = rootIndex\n\n\t\tfor (let i = 0; i < sorted.length; i++) {\n\t\t\tconst idx = sorted[i]\n\t\t\tif (this.#liteEntries[idx].entry.type === MSG_TYPE_DIRECTORY) {\n\t\t\t\tthis.#buildTree(idx)\n\t\t\t}\n\t\t}\n\t}\n\n\t#splitTree(sorted: number[], start: number, end: number, red: boolean): number {\n\t\tif (start >= end) return -1\n\t\tconst mid = Math.floor((start + end) / 2)\n\t\tconst entryIndex = sorted[mid]\n\t\tconst entry = this.#liteEntries[entryIndex]\n\t\tentry.red = red\n\t\tentry.left = this.#splitTree(sorted, start, mid, !red)\n\t\tentry.right = this.#splitTree(sorted, mid + 1, end, !red)\n\t\treturn entryIndex\n\t}\n\n\t// === DIFAT Builder\n\n\t#buildDifat(\n\t\tdifat1: number[],\n\t\tdifat2: number[],\n\t\tnumFatSectors: number,\n\t\tfirstFatSector: number,\n\t\tfirstDifatSector: number,\n\t): void {\n\t\tlet x = 0\n\t\tfor (; x < MSG_BURNER_DIFAT_HEADER_SLOTS && x < numFatSectors; x++) {\n\t\t\tdifat1.push(firstFatSector + x)\n\t\t}\n\t\tlet nextDifatSector = firstDifatSector + 1\n\t\tfor (; x < numFatSectors; x++) {\n\t\t\tdifat2.push(firstFatSector + x)\n\t\t\tif ((difat2.length & 127) === 127) {\n\t\t\t\tdifat2.push(nextDifatSector)\n\t\t\t\tnextDifatSector++\n\t\t\t}\n\t\t}\n\t\twhile (difat2.length > 0 && (difat2.length & 127) !== 0) {\n\t\t\tconst remain = difat2.length & 127\n\t\t\tdifat2.push(remain === 127 ? MSG_END_OF_CHAIN : MSG_UNUSED_BLOCK)\n\t\t}\n\t}\n\n\t// === Binary Writers\n\n\t#writeHeader(\n\t\tview: DataView,\n\t\tbytes: Uint8Array,\n\t\tnumFatSectors: number,\n\t\tentriesFirstSector: number,\n\t\tfirstMiniFatSector: number,\n\t\tnumMiniFatSectors: number,\n\t\tfirstDifatSector: number,\n\t\tnumDifatSectors: number,\n\t\tdifat1: number[],\n\t): void {\n\t\tbytes.set(MSG_FILE_HEADER, 0)\n\t\tview.setUint16(0x18, 0x3e, true)\n\t\tview.setUint16(0x1a, 0x03, true)\n\t\tview.setUint16(0x1c, 0xfffe, true)\n\t\tview.setUint16(0x1e, 9, true)\n\t\tview.setUint16(0x20, 6, true)\n\n\t\tview.setInt32(0x2c, numFatSectors, true)\n\t\tview.setInt32(0x30, entriesFirstSector, true)\n\n\t\tview.setInt32(0x38, MSG_BURNER_MINI_STREAM_CUTOFF, true)\n\t\tview.setInt32(0x3c, firstMiniFatSector, true)\n\t\tview.setInt32(0x40, numMiniFatSectors, true)\n\t\tview.setInt32(0x44, firstDifatSector, true)\n\t\tview.setInt32(0x48, numDifatSectors, true)\n\n\t\tlet offset = 0x4c\n\t\tfor (let i = 0; i < difat1.length; i++) {\n\t\t\tview.setInt32(offset, difat1[i], true)\n\t\t\toffset += 4\n\t\t}\n\t\tfor (let i = difat1.length; i < MSG_BURNER_DIFAT_HEADER_SLOTS; i++) {\n\t\t\tview.setInt32(offset, MSG_UNUSED_BLOCK, true)\n\t\t\toffset += 4\n\t\t}\n\t}\n\n\t#writeDirectoryEntries(\n\t\tview: DataView,\n\t\tbytes: Uint8Array,\n\t\tentriesFirstSector: number,\n\t\tbytesMiniFat: number,\n\t): void {\n\t\tfor (let x = 0; x < this.#liteEntries.length; x++) {\n\t\t\tconst le = this.#liteEntries[x]\n\t\t\tconst pos = MSG_BURNER_SECTOR_SIZE * (1 + entriesFirstSector) + MSG_BURNER_DIR_ENTRY_SIZE * x\n\n\t\t\t// CFB caps a directory entry name at MSG_BURNER_NAME_MAX UTF-16 code\n\t\t\t// units + a NUL terminator inside the fixed 64-byte name field\n\t\t\t// (offsets 0x00-0x3f). A longer name would overrun into the\n\t\t\t// type/color/sibling fields that follow, so validate before\n\t\t\t// writing any name bytes.\n\t\t\tconst name = le.entry.name\n\t\t\tif (name.length > MSG_BURNER_NAME_MAX) {\n\t\t\t\tthrow new MSGError(\n\t\t\t\t\t'BURN',\n\t\t\t\t\t`directory entry name exceeds ${MSG_BURNER_NAME_MAX} characters`,\n\t\t\t\t\t{ name },\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tfor (let i = 0; i < name.length; i++) {\n\t\t\t\tview.setUint16(pos + i * 2, name.charCodeAt(i), true)\n\t\t\t}\n\t\t\t// NUL terminator + recorded byte length: (chars + 1) UTF-16 units.\n\t\t\tview.setUint16(pos + name.length * 2, 0, true)\n\n\t\t\tview.setUint16(pos + 0x40, (name.length + 1) * 2, true)\n\t\t\tbytes[pos + 0x42] = le.entry.type\n\t\t\tbytes[pos + 0x43] = le.red ? 0 : 1\n\t\t\tview.setInt32(pos + 0x44, le.left, true)\n\t\t\tview.setInt32(pos + 0x48, le.right, true)\n\t\t\tview.setInt32(pos + 0x4c, le.child, true)\n\n\t\t\tif (x === 0) {\n\t\t\t\tbytes.set(MSG_BURNER_ROOT_CLSID, pos + 0x50)\n\t\t\t}\n\n\t\t\tconst length = x === 0 ? bytesMiniFat : le.entry.length\n\t\t\tconst firstSector =\n\t\t\t\tlength !== 0 ? le.firstSector : le.entry.type === MSG_TYPE_DIRECTORY ? 0 : MSG_END_OF_CHAIN\n\n\t\t\tview.setInt32(pos + 0x74, firstSector, true)\n\t\t\tview.setInt32(pos + 0x78, length, true)\n\t\t}\n\t}\n\n\t#writeLargeStreams(bytes: Uint8Array): void {\n\t\tfor (let i = 0; i < this.#liteEntries.length; i++) {\n\t\t\tconst le = this.#liteEntries[i]\n\t\t\tif (\n\t\t\t\tle.entry.type === MSG_TYPE_DOCUMENT &&\n\t\t\t\t!le.mini &&\n\t\t\t\tle.entry.binaryProvider !== undefined\n\t\t\t) {\n\t\t\t\tconst data = le.entry.binaryProvider()\n\t\t\t\tbytes.set(data, MSG_BURNER_SECTOR_SIZE * (1 + le.firstSector))\n\t\t\t}\n\t\t}\n\t}\n\n\t#writeMiniStreams(bytes: Uint8Array, firstMiniDataSector: number): void {\n\t\tif (firstMiniDataSector === MSG_END_OF_CHAIN) return\n\n\t\tfor (let i = 0; i < this.#liteEntries.length; i++) {\n\t\t\tconst le = this.#liteEntries[i]\n\t\t\tif (le.entry.type === MSG_TYPE_DOCUMENT && le.mini && le.entry.binaryProvider !== undefined) {\n\t\t\t\tconst data = le.entry.binaryProvider()\n\t\t\t\tbytes.set(\n\t\t\t\t\tdata,\n\t\t\t\t\tMSG_BURNER_SECTOR_SIZE * (1 + firstMiniDataSector) +\n\t\t\t\t\t\tMSG_BURNER_MINI_SECTOR_SIZE * le.firstSector,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t#writeMiniFat(view: DataView, firstMiniFatSector: number): void {\n\t\tif (firstMiniFatSector === MSG_END_OF_CHAIN) return\n\n\t\tlet offset = MSG_BURNER_SECTOR_SIZE * (1 + firstMiniFatSector)\n\t\tfor (let i = 0; i < this.#miniFat.length; i++) {\n\t\t\tview.setInt32(offset, this.#miniFat[i], true)\n\t\t\toffset += 4\n\t\t}\n\t}\n\n\t#writeFat(view: DataView, firstFatSector: number): void {\n\t\twhile (this.#fat.length % MSG_BURNER_INTS_PER_SECTOR !== 0) {\n\t\t\tthis.#fat.push(MSG_UNUSED_BLOCK)\n\t\t}\n\n\t\tlet offset = MSG_BURNER_SECTOR_SIZE * (1 + firstFatSector)\n\t\tfor (let i = 0; i < this.#fat.length; i++) {\n\t\t\tview.setInt32(offset, this.#fat[i], true)\n\t\t\toffset += 4\n\t\t}\n\t}\n\n\t#writeDifat(\n\t\tview: DataView,\n\t\tdifat2: number[],\n\t\tfirstDifatSector: number,\n\t\tnumDifatSectors: number,\n\t): void {\n\t\tif (numDifatSectors < 1) return\n\n\t\tlet offset = MSG_BURNER_SECTOR_SIZE * (1 + firstDifatSector)\n\t\tfor (let i = 0; i < difat2.length; i++) {\n\t\t\tview.setInt32(offset, difat2[i], true)\n\t\t\toffset += 4\n\t\t}\n\t}\n}\n","/**\n * MSGReader\n *\n * Parses Microsoft Outlook .msg files (CFB/OLE2 compound binary format).\n * Extracts message fields, recipients, and attachments using native\n * DataView operations with no external dependencies.\n */\n\nimport type {\n\tMSGReaderInterface,\n\tMSGReaderOptions,\n\tMSGFieldData,\n\tMSGAttachment,\n\tMSGRecipientRole,\n\tMSGDirectoryEntry,\n\tMSGMutableFieldData,\n\tMSGNameIdEntry,\n\tMSGBurnerEntry,\n} from './types.js'\nimport { MSGError } from './errors.js'\nimport {\n\tMSG_END_OF_CHAIN,\n\tMSG_UNUSED_BLOCK,\n\tMSG_S_BIG_BLOCK_SIZE,\n\tMSG_L_BIG_BLOCK_SIZE,\n\tMSG_L_BIG_BLOCK_MARK,\n\tMSG_SMALL_BLOCK_SIZE,\n\tMSG_BIG_BLOCK_MIN_DOC_SIZE,\n\tMSG_HEADER_PROPERTY_START_OFFSET,\n\tMSG_HEADER_BAT_START_OFFSET,\n\tMSG_HEADER_BAT_COUNT_OFFSET,\n\tMSG_HEADER_SBAT_START_OFFSET,\n\tMSG_HEADER_SBAT_COUNT_OFFSET,\n\tMSG_HEADER_XBAT_START_OFFSET,\n\tMSG_HEADER_XBAT_COUNT_OFFSET,\n\tMSG_PROP_NO_INDEX,\n\tMSG_PROPERTY_SIZE,\n\tMSG_PROP_NAME_SIZE_OFFSET,\n\tMSG_PROP_TYPE_OFFSET,\n\tMSG_PROP_PREVIOUS_PROPERTY_OFFSET,\n\tMSG_PROP_NEXT_PROPERTY_OFFSET,\n\tMSG_PROP_CHILD_PROPERTY_OFFSET,\n\tMSG_PROP_START_BLOCK_OFFSET,\n\tMSG_PROP_SIZE_OFFSET,\n\tMSG_TYPE_DIRECTORY,\n\tMSG_TYPE_DOCUMENT,\n\tMSG_TYPE_ROOT,\n\tMSG_PREFIX_ATTACHMENT,\n\tMSG_PREFIX_RECIPIENT,\n\tMSG_PREFIX_DOCUMENT,\n\tMSG_PREFIX_NAMEID,\n\tMSG_FIELD_NAME_MAPPING,\n\tMSG_FIELD_FULL_NAME_MAPPING,\n\tMSG_FIELD_TYPE_MAPPING,\n\tMSG_FIELD_CLASS_ATTACHMENT_DATA,\n\tMSG_FIELD_DIR_TYPE_INNER_MSG,\n\tMSG_PIDLID_MAPPING,\n\tMSG_MAPI_RECIPIENT_TO,\n\tMSG_MAPI_RECIPIENT_CC,\n\tMSG_MAPI_RECIPIENT_BCC,\n\tMSG_BURNER_NAME_MAX,\n\tMSG_MAX_HIERARCHY_DEPTH,\n} from './constants.js'\nimport {\n\tisMSGFile,\n\tremoveTrailingNull,\n\treadUTF16String,\n\treadANSIString,\n\tfileTimeToUTCString,\n\ttoHexLower,\n\tmsftUUIDStringify,\n} from './helpers.js'\nimport { MSGBurner } from './MSGBurner.js'\n// === MSGReader\n\n/**\n * Parses Microsoft Outlook .msg files (CFB/OLE2 compound binary format).\n * Every parsing step treats the input as untrusted: sector and property\n * chains are cycle-guarded and length-capped, every raw byte range is\n * bounds-checked before a view is constructed over it, and every failure\n * surfaces as a typed {@link MSGError} rather than a raw `RangeError` or\n * `TypeError`.\n */\nexport class MSGReader implements MSGReaderInterface {\n\treadonly #view: DataView\n\treadonly #byteLength: number\n\treadonly #totalSectors: number\n\treadonly #options: MSGReaderOptions\n\t#bigBlockSize = 0\n\t#bigBlockLength = 0\n\t#xBlockLength = 0\n\t#batCount = 0\n\t#propertyStart = 0\n\t#sbatStart = 0\n\t#sbatCount = 0\n\t#xbatStart = 0\n\t#xbatCount = 0\n\t#bat: number[] = []\n\t#sbat: number[] = []\n\t#properties: MSGDirectoryEntry[] = []\n\t#bigBlockTable: number[] = []\n\t#fields: MSGFieldData | undefined\n\t#privatePidToKeyed: Record<number, MSGNameIdEntry> = {}\n\t#innerMSGBurners: Record<number, () => Uint8Array> = {}\n\n\t/**\n\t * Create a reader over a raw MSG file buffer.\n\t *\n\t * @param input - Raw MSG file bytes, as an `ArrayBuffer` or a `Uint8Array` view\n\t * @param options - Reader configuration\n\t */\n\tconstructor(input: ArrayBuffer | Uint8Array, options?: MSGReaderOptions) {\n\t\tif (input instanceof Uint8Array) {\n\t\t\tthis.#view = new DataView(input.buffer, input.byteOffset, input.byteLength)\n\t\t\tthis.#byteLength = input.byteLength\n\t\t} else {\n\t\t\tthis.#view = new DataView(input)\n\t\t\tthis.#byteLength = input.byteLength\n\t\t}\n\t\tthis.#options = options ?? {}\n\t\tthis.#totalSectors = Math.ceil(this.#byteLength / MSG_S_BIG_BLOCK_SIZE)\n\t}\n\n\t/**\n\t * Parse the MSG file and return extracted field data.\n\t *\n\t * @returns Root message field data with nested attachments and recipients\n\t * @throws {@link MSGError} with code `UNSUPPORTED`, `MALFORMED`, `CYCLE`,\n\t * or `RANGE` when the compound file cannot be parsed\n\t */\n\tparse(): MSGFieldData {\n\t\tif (this.#fields !== undefined) return this.#fields\n\n\t\tthis.#parseHeader()\n\t\tthis.#bat = this.#readBat()\n\t\tif (this.#xbatCount > 0) {\n\t\t\tthis.#readXbat()\n\t\t}\n\t\tthis.#sbat = this.#readSbat()\n\t\tthis.#properties = this.#readProperties(this.#propertyStart)\n\t\tthis.#bigBlockTable = this.#buildBigBlockTable()\n\t\tthis.#privatePidToKeyed = {}\n\t\tthis.#innerMSGBurners = {}\n\n\t\tconst fields = this.#extractFields()\n\t\tthis.#fields = fields\n\t\treturn fields\n\t}\n\n\t/**\n\t * Read attachment binary content by index.\n\t *\n\t * @param index - Zero-based index into the parsed attachment list\n\t * @returns File name and raw binary content\n\t * @throws {@link MSGError} with code `RANGE` when the index is out of bounds\n\t */\n\tattachment(index: number): MSGAttachment {\n\t\tconst parsed = this.parse()\n\t\tconst attachments = parsed.attachments\n\t\tif (attachments === undefined || index < 0 || index >= attachments.length) {\n\t\t\tthrow new MSGError('RANGE', `Attachment index ${index} out of range`, { index })\n\t\t}\n\n\t\tconst attach = attachments[index]\n\t\tif (attach.innerMSGContent === true && typeof attach.folderId === 'number') {\n\t\t\tconst name = typeof attach.name === 'string' ? attach.name : 'embedded'\n\t\t\tconst burner = this.#innerMSGBurners[attach.folderId]\n\t\t\tconst content = burner !== undefined ? burner() : new Uint8Array(0)\n\t\t\treturn { fileName: name + '.msg', content }\n\t\t}\n\n\t\tif (\n\t\t\ttypeof attach.dataId !== 'number' ||\n\t\t\tattach.dataId < 0 ||\n\t\t\tattach.dataId >= this.#properties.length\n\t\t) {\n\t\t\tthrow new MSGError('RANGE', 'Attachment has no valid data reference', { index })\n\t\t}\n\n\t\tconst entry = this.#properties[attach.dataId]\n\t\tconst content = this.#readEntry(entry)\n\t\tconst fileName =\n\t\t\ttypeof attach.fileName === 'string'\n\t\t\t\t? attach.fileName\n\t\t\t\t: typeof attach.fileNameShort === 'string'\n\t\t\t\t\t? attach.fileNameShort\n\t\t\t\t\t: typeof attach.name === 'string'\n\t\t\t\t\t\t? attach.name\n\t\t\t\t\t\t: 'unknown'\n\n\t\treturn { fileName, content }\n\t}\n\n\t/**\n\t * Rebuild the parsed MSG as a standalone CFB/.msg binary.\n\t *\n\t * @returns Complete CFB byte stream\n\t * @throws {@link MSGError} with code `BURN` when the parsed structure\n\t * cannot be reconstituted\n\t */\n\tburn(): Uint8Array {\n\t\tconst parsed = this.parse()\n\t\tif (parsed.kind !== 'msg') {\n\t\t\tthrow new MSGError('BURN', 'Unable to burn a non-message field data structure', {\n\t\t\t\tkind: parsed.kind,\n\t\t\t})\n\t\t}\n\n\t\tconst root = this.#properties[0]\n\t\tif (root === undefined) {\n\t\t\tthrow new MSGError('BURN', 'Unable to burn MSG file without a root entry')\n\t\t}\n\n\t\treturn this.#burnFolder(root, false, false)\n\t}\n\n\t// === Header Parsing\n\n\t#parseHeader(): void {\n\t\tif (!isMSGFile(this.#view)) {\n\t\t\tthrow new MSGError('UNSUPPORTED', 'Input is not a recognized CFB/MSG file')\n\t\t}\n\t\tif (this.#byteLength < MSG_S_BIG_BLOCK_SIZE) {\n\t\t\tthrow new MSGError('MALFORMED', 'File is smaller than the minimum CFB header size', {\n\t\t\t\tbyteLength: this.#byteLength,\n\t\t\t})\n\t\t}\n\n\t\tconst v = this.#view\n\t\tconst sectorMark = v.getUint8(30)\n\t\tthis.#bigBlockSize =\n\t\t\tsectorMark === MSG_L_BIG_BLOCK_MARK ? MSG_L_BIG_BLOCK_SIZE : MSG_S_BIG_BLOCK_SIZE\n\t\tthis.#bigBlockLength = this.#bigBlockSize / 4\n\t\tthis.#xBlockLength = this.#bigBlockLength - 1\n\n\t\tconst batCount = v.getInt32(MSG_HEADER_BAT_COUNT_OFFSET, true)\n\t\tconst propertyStart = v.getInt32(MSG_HEADER_PROPERTY_START_OFFSET, true)\n\t\tconst sbatStart = v.getInt32(MSG_HEADER_SBAT_START_OFFSET, true)\n\t\tconst sbatCount = v.getInt32(MSG_HEADER_SBAT_COUNT_OFFSET, true)\n\t\tconst xbatStart = v.getInt32(MSG_HEADER_XBAT_START_OFFSET, true)\n\t\tconst xbatCount = v.getInt32(MSG_HEADER_XBAT_COUNT_OFFSET, true)\n\n\t\tthis.#validateHeaderField('batCount', batCount)\n\t\tthis.#validateHeaderField('sbatCount', sbatCount)\n\t\tthis.#validateHeaderField('xbatCount', xbatCount)\n\t\tthis.#validateHeaderField('propertyStart', propertyStart)\n\n\t\tthis.#batCount = batCount\n\t\tthis.#propertyStart = propertyStart\n\t\tthis.#sbatStart = sbatStart\n\t\tthis.#sbatCount = sbatCount\n\t\tthis.#xbatStart = xbatStart\n\t\tthis.#xbatCount = xbatCount\n\t}\n\n\t// two words: validates a single header count/sector field against totalSectors\n\t#validateHeaderField(name: string, value: number): void {\n\t\tif (value < 0 || value > this.#totalSectors) {\n\t\t\tthrow new MSGError('MALFORMED', `CFB header field '${name}' is out of range`, {\n\t\t\t\tfield: name,\n\t\t\t\tvalue,\n\t\t\t})\n\t\t}\n\t}\n\n\t// bounds guard shared by every raw byte-range read over the file view\n\t#assertBounds(start: number, length: number): void {\n\t\tif (start < 0 || length < 0 || start + length > this.#byteLength) {\n\t\t\tthrow new MSGError('MALFORMED', 'Computed byte range exceeds file bounds', {\n\t\t\t\tstart,\n\t\t\t\tlength,\n\t\t\t\tbyteLength: this.#byteLength,\n\t\t\t})\n\t\t}\n\t}\n\n\t// cycle guard shared by every sector-chain walk; each domain supplies its\n\t// own capacity (big-sector chains cap at totalSectors, the small-block\n\t// chain caps at the mini-FAT's own capacity) so a mini-stream chain -\n\t// which routinely has far more links than the file has big sectors - is\n\t// never conflated with a big-sector chain's cap\n\t#trackSector(\n\t\tvisited: Set<number>,\n\t\tsector: number,\n\t\tlabel: string,\n\t\tlimit: number,\n\t\tcapacityLabel: string,\n\t): void {\n\t\tif (visited.has(sector)) {\n\t\t\tthrow new MSGError('CYCLE', `${label} chain revisits sector ${sector}`, { sector })\n\t\t}\n\t\tif (visited.size >= limit) {\n\t\t\tthrow new MSGError('CYCLE', `${label} chain exceeds ${capacityLabel}`, {\n\t\t\t\tlimit,\n\t\t\t})\n\t\t}\n\t\tvisited.add(sector)\n\t}\n\n\t// === FAT (Block Allocation Table)\n\n\t#batCountInHeader(): number {\n\t\tconst max = (MSG_S_BIG_BLOCK_SIZE - MSG_HEADER_BAT_START_OFFSET) / 4\n\t\treturn Math.min(this.#batCount, max)\n\t}\n\n\t#readBat(): number[] {\n\t\tconst count = this.#batCountInHeader()\n\t\tconst result: number[] = new Array(count)\n\t\tlet offset = MSG_HEADER_BAT_START_OFFSET\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tresult[i] = this.#view.getInt32(offset, true)\n\t\t\toffset += 4\n\t\t}\n\t\treturn result\n\t}\n\n\t#blockOffset(sector: number): number {\n\t\tif (sector < 0 || sector >= this.#totalSectors) {\n\t\t\tthrow new MSGError('MALFORMED', `Sector index out of range: ${sector}`, {\n\t\t\t\tsector,\n\t\t\t\ttotalSectors: this.#totalSectors,\n\t\t\t})\n\t\t}\n\t\treturn (sector + 1) * this.#bigBlockSize\n\t}\n\n\t#blockValueAt(sector: number, index: number): number {\n\t\tconst offset = this.#blockOffset(sector) + 4 * index\n\t\tthis.#assertBounds(offset, 4)\n\t\treturn this.#view.getInt32(offset, true)\n\t}\n\n\t#nextBlockInner(offset: number, table: number[]): number {\n\t\tconst block = Math.floor(offset / this.#bigBlockLength)\n\t\tconst index = offset % this.#bigBlockLength\n\t\tconst sector = table[block]\n\t\tif (sector === undefined) return MSG_END_OF_CHAIN\n\t\treturn this.#blockValueAt(sector, index)\n\t}\n\n\t#nextBlock(offset: number): number {\n\t\treturn this.#nextBlockInner(offset, this.#bat)\n\t}\n\n\t#nextBlockSmall(offset: number): number {\n\t\treturn this.#nextBlockInner(offset, this.#sbat)\n\t}\n\n\t// === SBAT (Small Block Allocation Table)\n\n\t#readSbat(): number[] {\n\t\tconst result: number[] = []\n\t\tconst visited = new Set<number>()\n\t\tlet startIndex = this.#sbatStart\n\t\tfor (\n\t\t\tlet i = 0;\n\t\t\ti < this.#sbatCount && startIndex !== 0 && startIndex !== MSG_END_OF_CHAIN;\n\t\t\ti++\n\t\t) {\n\t\t\tthis.#trackSector(visited, startIndex, 'SBAT', this.#totalSectors, 'total sector count')\n\t\t\tresult.push(startIndex)\n\t\t\tstartIndex = this.#nextBlock(startIndex)\n\t\t}\n\t\treturn result\n\t}\n\n\t// === XBAT (Extended BAT / DIFAT)\n\n\t#readXbat(): void {\n\t\tconst headerBatCount = this.#batCountInHeader()\n\t\tlet remaining = this.#batCount - headerBatCount\n\t\tlet nextSector = this.#xbatStart\n\t\tconst visited = new Set<number>()\n\n\t\tfor (let i = 0; i < this.#xbatCount; i++) {\n\t\t\tthis.#trackSector(visited, nextSector, 'XBAT', this.#totalSectors, 'total sector count')\n\t\t\tconst blockOffset = this.#blockOffset(nextSector)\n\t\t\tthis.#assertBounds(blockOffset, this.#bigBlockSize)\n\t\t\tconst toProcess = Math.min(remaining, this.#xBlockLength)\n\n\t\t\tfor (let j = 0; j < toProcess; j++) {\n\t\t\t\tconst sector = this.#view.getInt32(blockOffset + j * 4, true)\n\t\t\t\tif (sector === MSG_UNUSED_BLOCK || sector === MSG_END_OF_CHAIN) break\n\t\t\t\tthis.#bat.push(sector)\n\t\t\t}\n\t\t\tremaining -= toProcess\n\n\t\t\tnextSector = this.#view.getInt32(blockOffset + this.#xBlockLength * 4, true)\n\t\t\tif (nextSector === MSG_UNUSED_BLOCK || nextSector === MSG_END_OF_CHAIN) break\n\t\t}\n\t}\n\n\t// === Directory Entry Parsing\n\n\t#readEntryName(offset: number): string {\n\t\tconst nameBytes = this.#view.getUint16(offset + MSG_PROP_NAME_SIZE_OFFSET, true)\n\t\tif (nameBytes < 2) return ''\n\t\t// The fixed 64-byte CFB name field holds at most 32 UTF-16 units\n\t\t// including the NUL terminator, so a hostile name-size field is\n\t\t// clamped to that field's own capacity before it is ever read.\n\t\tconst charCount = Math.min(nameBytes / 2 - 1, MSG_BURNER_NAME_MAX)\n\t\treturn removeTrailingNull(readUTF16String(this.#view, offset, charCount))\n\t}\n\n\t#readDirectoryEntry(offset: number): MSGDirectoryEntry {\n\t\tconst v = this.#view\n\t\treturn {\n\t\t\ttype: v.getUint8(offset + MSG_PROP_TYPE_OFFSET),\n\t\t\tname: this.#readEntryName(offset),\n\t\t\tpreviousProperty: v.getInt32(offset + MSG_PROP_PREVIOUS_PROPERTY_OFFSET, true),\n\t\t\tnextProperty: v.getInt32(offset + MSG_PROP_NEXT_PROPERTY_OFFSET, true),\n\t\t\tchildProperty: v.getInt32(offset + MSG_PROP_CHILD_PROPERTY_OFFSET, true),\n\t\t\tstartBlock: v.getInt32(offset + MSG_PROP_START_BLOCK_OFFSET, true),\n\t\t\tsizeBlock: v.getInt32(offset + MSG_PROP_SIZE_OFFSET, true),\n\t\t}\n\t}\n\n\t#readProperties(propertyStart: number): MSGDirectoryEntry[] {\n\t\tconst props: MSGDirectoryEntry[] = []\n\t\tconst visited = new Set<number>()\n\t\tlet currentSector = propertyStart\n\n\t\twhile (currentSector !== MSG_END_OF_CHAIN) {\n\t\t\tthis.#trackSector(\n\t\t\t\tvisited,\n\t\t\t\tcurrentSector,\n\t\t\t\t'Property',\n\t\t\t\tthis.#totalSectors,\n\t\t\t\t'total sector count',\n\t\t\t)\n\t\t\tconst entryCount = this.#bigBlockSize / MSG_PROPERTY_SIZE\n\t\t\tlet offset = this.#blockOffset(currentSector)\n\n\t\t\tfor (let i = 0; i < entryCount; i++) {\n\t\t\t\tif (offset + MSG_PROPERTY_SIZE > this.#byteLength) break\n\t\t\t\tconst entryType = this.#view.getUint8(offset + MSG_PROP_TYPE_OFFSET)\n\n\t\t\t\tif (\n\t\t\t\t\tentryType === MSG_TYPE_ROOT ||\n\t\t\t\t\tentryType === MSG_TYPE_DIRECTORY ||\n\t\t\t\t\tentryType === MSG_TYPE_DOCUMENT\n\t\t\t\t) {\n\t\t\t\t\tprops.push(this.#readDirectoryEntry(offset))\n\t\t\t\t} else {\n\t\t\t\t\tprops.push({\n\t\t\t\t\t\ttype: entryType,\n\t\t\t\t\t\tname: '',\n\t\t\t\t\t\tpreviousProperty: -1,\n\t\t\t\t\t\tnextProperty: -1,\n\t\t\t\t\t\tchildProperty: -1,\n\t\t\t\t\t\tstartBlock: 0,\n\t\t\t\t\t\tsizeBlock: 0,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\toffset += MSG_PROPERTY_SIZE\n\t\t\t}\n\t\t\tcurrentSector = this.#nextBlock(currentSector)\n\t\t}\n\n\t\tif (props.length > 0) {\n\t\t\tthis.#buildHierarchy(props, 0, new Set<number>(), 0)\n\t\t}\n\t\treturn props\n\t}\n\n\t#buildHierarchy(\n\t\tprops: MSGDirectoryEntry[],\n\t\tnodeIndex: number,\n\t\tvisited: Set<number>,\n\t\tdepth: number,\n\t): void {\n\t\tconst node = props[nodeIndex]\n\t\tif (node === undefined || node.childProperty === MSG_PROP_NO_INDEX) return\n\n\t\tif (depth > MSG_MAX_HIERARCHY_DEPTH) {\n\t\t\tthrow new MSGError('CYCLE', 'Directory hierarchy nesting exceeds maximum depth', {\n\t\t\t\tdepth,\n\t\t\t\tmax: MSG_MAX_HIERARCHY_DEPTH,\n\t\t\t})\n\t\t}\n\t\tif (visited.has(nodeIndex)) {\n\t\t\tthrow new MSGError('CYCLE', `Directory hierarchy revisits property index ${nodeIndex}`, {\n\t\t\t\tindex: nodeIndex,\n\t\t\t})\n\t\t}\n\t\tif (visited.size >= props.length) {\n\t\t\tthrow new MSGError('CYCLE', 'Directory hierarchy traversal exceeds total property count', {\n\t\t\t\tlimit: props.length,\n\t\t\t})\n\t\t}\n\t\tvisited.add(nodeIndex)\n\t\tnode.children = []\n\n\t\tconst siblingVisited = new Set<number>([node.childProperty])\n\t\tconst stack: Array<{ mode: string; index: number }> = [\n\t\t\t{ mode: 'walk', index: node.childProperty },\n\t\t]\n\n\t\twhile (stack.length > 0) {\n\t\t\tconst item = stack.pop()\n\t\t\tif (item === undefined) break\n\t\t\tconst current = props[item.index]\n\t\t\tif (current === undefined) continue\n\n\t\t\tif (item.mode === 'push') {\n\t\t\t\tnode.children.push(item.index)\n\t\t\t} else {\n\t\t\t\tif (current.type === MSG_TYPE_DIRECTORY) {\n\t\t\t\t\tthis.#buildHierarchy(props, item.index, visited, depth + 1)\n\t\t\t\t}\n\t\t\t\tif (current.nextProperty !== MSG_PROP_NO_INDEX) {\n\t\t\t\t\tif (siblingVisited.has(current.nextProperty)) {\n\t\t\t\t\t\tthrow new MSGError(\n\t\t\t\t\t\t\t'CYCLE',\n\t\t\t\t\t\t\t`Directory sibling chain revisits property index ${current.nextProperty}`,\n\t\t\t\t\t\t\t{ index: current.nextProperty },\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tsiblingVisited.add(current.nextProperty)\n\t\t\t\t\tstack.push({ mode: 'walk', index: current.nextProperty })\n\t\t\t\t}\n\t\t\t\tstack.push({ mode: 'push', index: item.index })\n\t\t\t\tif (current.previousProperty !== MSG_PROP_NO_INDEX) {\n\t\t\t\t\tif (siblingVisited.has(current.previousProperty)) {\n\t\t\t\t\t\tthrow new MSGError(\n\t\t\t\t\t\t\t'CYCLE',\n\t\t\t\t\t\t\t`Directory sibling chain revisits property index ${current.previousProperty}`,\n\t\t\t\t\t\t\t{ index: current.previousProperty },\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tsiblingVisited.add(current.previousProperty)\n\t\t\t\t\tstack.push({ mode: 'walk', index: current.previousProperty })\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// === Big Block Table (mini-stream container chain)\n\n\t#buildBigBlockTable(): number[] {\n\t\tconst rootProp = this.#properties[0]\n\t\tif (rootProp === undefined) return []\n\n\t\tconst table: number[] = []\n\t\tconst visited = new Set<number>()\n\t\tlet nextBlock = rootProp.startBlock\n\t\twhile (nextBlock !== MSG_END_OF_CHAIN) {\n\t\t\tthis.#trackSector(visited, nextBlock, 'Big block', this.#totalSectors, 'total sector count')\n\t\t\ttable.push(nextBlock)\n\t\t\tnextBlock = this.#nextBlock(nextBlock)\n\t\t}\n\t\treturn table\n\t}\n\n\t// === Data Reading\n\n\t#readSmallBlockData(\n\t\tstartBlock: number,\n\t\tblockSize: number,\n\t\tdest: Uint8Array,\n\t\tdestOffset: number,\n\t): void {\n\t\tconst byteOffset = startBlock * MSG_SMALL_BLOCK_SIZE\n\t\tconst bigBlockNumber = Math.floor(byteOffset / this.#bigBlockSize)\n\t\tconst bigBlockOffset = byteOffset % this.#bigBlockSize\n\n\t\tconst sector = this.#bigBlockTable[bigBlockNumber]\n\t\tif (sector === undefined) return\n\t\tconst start = this.#blockOffset(sector) + bigBlockOffset\n\t\tthis.#assertBounds(start, blockSize)\n\t\tconst src = new Uint8Array(this.#view.buffer, this.#view.byteOffset + start, blockSize)\n\t\tdest.set(src, destOffset)\n\t}\n\n\t#readSmallChainData(entry: MSGDirectoryEntry, chain: number[]): Uint8Array {\n\t\tconst result = new Uint8Array(entry.sizeBlock)\n\t\tlet idx = 0\n\t\tfor (let i = 0; i < chain.length; i++) {\n\t\t\tconst readLen = Math.min(result.length - idx, MSG_SMALL_BLOCK_SIZE)\n\t\t\tthis.#readSmallBlockData(chain[i], readLen, result, idx)\n\t\t\tidx += readLen\n\t\t}\n\t\treturn result\n\t}\n\n\t#smallBlockChain(entry: MSGDirectoryEntry): number[] {\n\t\tconst chain: number[] = []\n\t\tconst visited = new Set<number>()\n\t\t// the mini-FAT lives in this.#sbat's big sectors, each holding\n\t\t// bigBlockLength int32 entries - that flat entry count, not the\n\t\t// file's big-sector count, bounds a legitimate mini-stream chain\n\t\tconst capacity = this.#sbat.length * this.#bigBlockLength\n\t\tlet next = entry.startBlock\n\t\twhile (next !== MSG_END_OF_CHAIN) {\n\t\t\tif (next < 0 || next >= capacity) {\n\t\t\t\tthrow new MSGError('MALFORMED', `Small block index ${next} exceeds mini-FAT capacity`, {\n\t\t\t\t\tsector: next,\n\t\t\t\t\tcapacity,\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.#trackSector(visited, next, 'Small block', capacity, 'mini-FAT capacity')\n\t\t\tchain.push(next)\n\t\t\tnext = this.#nextBlockSmall(next)\n\t\t}\n\t\treturn chain\n\t}\n\n\t#readEntry(entry: MSGDirectoryEntry): Uint8Array {\n\t\tif (entry.sizeBlock <= 0) return new Uint8Array(0)\n\t\tif (entry.sizeBlock > this.#byteLength) {\n\t\t\tthrow new MSGError('MALFORMED', 'Directory entry size exceeds file bounds', {\n\t\t\t\tsizeBlock: entry.sizeBlock,\n\t\t\t\tbyteLength: this.#byteLength,\n\t\t\t})\n\t\t}\n\n\t\tif (entry.sizeBlock < MSG_BIG_BLOCK_MIN_DOC_SIZE) {\n\t\t\tconst chain = this.#smallBlockChain(entry)\n\t\t\tif (chain.length === 1) {\n\t\t\t\tconst result = new Uint8Array(entry.sizeBlock)\n\t\t\t\tthis.#readSmallBlockData(entry.startBlock, entry.sizeBlock, result, 0)\n\t\t\t\treturn result\n\t\t\t} else if (chain.length > 1) {\n\t\t\t\treturn this.#readSmallChainData(entry, chain)\n\t\t\t}\n\t\t\treturn new Uint8Array(0)\n\t\t}\n\n\t\t// Large block reading\n\t\tlet nextBlock = entry.startBlock\n\t\tlet remaining = entry.sizeBlock\n\t\tlet position = 0\n\t\tconst result = new Uint8Array(entry.sizeBlock)\n\t\tconst visited = new Set<number>()\n\n\t\twhile (remaining >= 1) {\n\t\t\tthis.#trackSector(visited, nextBlock, 'Entry block', this.#totalSectors, 'total sector count')\n\t\t\tconst start = this.#blockOffset(nextBlock)\n\t\t\tconst partSize = Math.min(remaining, this.#bigBlockSize)\n\t\t\tthis.#assertBounds(start, partSize)\n\t\t\tconst src = new Uint8Array(this.#view.buffer, this.#view.byteOffset + start, partSize)\n\t\t\tresult.set(src, position)\n\t\t\tposition += partSize\n\t\t\tremaining -= partSize\n\t\t\tnextBlock = this.#nextBlock(nextBlock)\n\t\t}\n\t\treturn result\n\t}\n\n\t// === Field Extraction\n\n\t#extractFields(): MSGFieldData {\n\t\tconst root = this.#properties[0]\n\t\tif (root === undefined) {\n\t\t\tthrow new MSGError('MALFORMED', 'MSG file has no root directory entry')\n\t\t}\n\n\t\tconst fields: MSGMutableFieldData = {\n\t\t\tkind: 'msg',\n\t\t\tattachments: [],\n\t\t\trecipients: [],\n\t\t}\n\t\tthis.#processDirectory(root, fields, 'root')\n\t\treturn this.#toFieldData(fields)\n\t}\n\n\t// narrows an unknown-typed mutable field to a string\n\t#str(mutable: MSGMutableFieldData, key: string): string | undefined {\n\t\tconst value = mutable[key]\n\t\treturn typeof value === 'string' ? value : undefined\n\t}\n\n\t// narrows an unknown-typed mutable field to a number\n\t#num(mutable: MSGMutableFieldData, key: string): number | undefined {\n\t\tconst value = mutable[key]\n\t\treturn typeof value === 'number' ? value : undefined\n\t}\n\n\t// narrows an unknown-typed mutable field to a boolean\n\t#bool(mutable: MSGMutableFieldData, key: string): boolean | undefined {\n\t\tconst value = mutable[key]\n\t\treturn typeof value === 'boolean' ? value : undefined\n\t}\n\n\t// narrows an unknown-typed mutable field to binary content\n\t#bin(mutable: MSGMutableFieldData, key: string): Uint8Array | undefined {\n\t\tconst value = mutable[key]\n\t\treturn value instanceof Uint8Array ? value : undefined\n\t}\n\n\t// narrows an unknown-typed mutable field to a recipient role\n\t#role(mutable: MSGMutableFieldData, key: string): MSGRecipientRole | undefined {\n\t\tconst value = mutable[key]\n\t\treturn value === 'to' || value === 'cc' || value === 'bcc' ? value : undefined\n\t}\n\n\t// builds the readonly public MSGFieldData explicitly, field by field,\n\t// from the mutable accumulator - no type assertions\n\t#toFieldData(mutable: MSGMutableFieldData): MSGFieldData {\n\t\tconst attachmentsSource = mutable.attachments\n\t\tconst attachments =\n\t\t\tattachmentsSource === undefined\n\t\t\t\t? undefined\n\t\t\t\t: attachmentsSource.map((entry) => this.#toFieldData(entry))\n\t\tconst recipientsSource = mutable.recipients\n\t\tconst recipients =\n\t\t\trecipientsSource === undefined\n\t\t\t\t? undefined\n\t\t\t\t: recipientsSource.map((entry) => this.#toFieldData(entry))\n\t\tconst innerSource = mutable.innerMSGContentFields\n\t\tconst innerMSGContentFields =\n\t\t\tinnerSource === undefined ? undefined : this.#toFieldData(innerSource)\n\n\t\treturn {\n\t\t\tkind: mutable.kind,\n\t\t\t// email properties\n\t\t\tsubject: this.#str(mutable, 'subject'),\n\t\t\tsenderName: this.#str(mutable, 'senderName'),\n\t\t\tsenderEmail: this.#str(mutable, 'senderEmail'),\n\t\t\tsenderAddressType: this.#str(mutable, 'senderAddressType'),\n\t\t\tsenderSMTPAddress: this.#str(mutable, 'senderSMTPAddress'),\n\t\t\tsentRepresentingSMTPAddress: this.#str(mutable, 'sentRepresentingSMTPAddress'),\n\t\t\tbody: this.#str(mutable, 'body'),\n\t\t\theaders: this.#str(mutable, 'headers'),\n\t\t\tbodyHTML: this.#str(mutable, 'bodyHTML'),\n\t\t\thtml: this.#bin(mutable, 'html'),\n\t\t\tcompressedRTF: this.#bin(mutable, 'compressedRTF'),\n\t\t\tmessageClass: this.#str(mutable, 'messageClass'),\n\t\t\tmessageFlags: this.#num(mutable, 'messageFlags'),\n\t\t\tmessageId: this.#str(mutable, 'messageId'),\n\t\t\tinternetCodepage: this.#num(mutable, 'internetCodepage'),\n\t\t\tmessageCodepage: this.#num(mutable, 'messageCodepage'),\n\t\t\tmessageLocaleId: this.#num(mutable, 'messageLocaleId'),\n\t\t\tclientSubmitTime: this.#str(mutable, 'clientSubmitTime'),\n\t\t\tmessageDeliveryTime: this.#str(mutable, 'messageDeliveryTime'),\n\t\t\tcreationTime: this.#str(mutable, 'creationTime'),\n\t\t\tlastModificationTime: this.#str(mutable, 'lastModificationTime'),\n\t\t\tlastModifierName: this.#str(mutable, 'lastModifierName'),\n\t\t\tcreatorSMTPAddress: this.#str(mutable, 'creatorSMTPAddress'),\n\t\t\tlastModifierSMTPAddress: this.#str(mutable, 'lastModifierSMTPAddress'),\n\t\t\tpreview: this.#str(mutable, 'preview'),\n\t\t\tconversationTopic: this.#str(mutable, 'conversationTopic'),\n\t\t\tnormalizedSubject: this.#str(mutable, 'normalizedSubject'),\n\t\t\t// recipient properties\n\t\t\tname: this.#str(mutable, 'name'),\n\t\t\temail: this.#str(mutable, 'email'),\n\t\t\taddressType: this.#str(mutable, 'addressType'),\n\t\t\tsmtpAddress: this.#str(mutable, 'smtpAddress'),\n\t\t\trecipientRole: this.#role(mutable, 'recipientRole'),\n\t\t\t// attachment properties\n\t\t\textension: this.#str(mutable, 'extension'),\n\t\t\tfileNameShort: this.#str(mutable, 'fileNameShort'),\n\t\t\tfileName: this.#str(mutable, 'fileName'),\n\t\t\tcontentId: this.#str(mutable, 'contentId'),\n\t\t\tattachmentHidden: this.#bool(mutable, 'attachmentHidden'),\n\t\t\tmimeType: this.#str(mutable, 'mimeType'),\n\t\t\tcontentLength: mutable.contentLength,\n\t\t\tdataId: mutable.dataId,\n\t\t\tfolderId: mutable.folderId,\n\t\t\tinnerMSGContent: mutable.innerMSGContent,\n\t\t\tinnerMSGContentFields,\n\t\t\tattachments,\n\t\t\trecipients,\n\t\t\t// contact properties\n\t\t\tdepartmentName: this.#str(mutable, 'departmentName'),\n\t\t\tmiddleName: this.#str(mutable, 'middleName'),\n\t\t\tgeneration: this.#str(mutable, 'generation'),\n\t\t\tsurname: this.#str(mutable, 'surname'),\n\t\t\tgivenName: this.#str(mutable, 'givenName'),\n\t\t\tcompanyName: this.#str(mutable, 'companyName'),\n\t\t\tjobTitle: this.#str(mutable, 'jobTitle'),\n\t\t\tlocation: this.#str(mutable, 'location'),\n\t\t\tpostalAddress: this.#str(mutable, 'postalAddress'),\n\t\t\tstreetAddress: this.#str(mutable, 'streetAddress'),\n\t\t\tpostalCode: this.#str(mutable, 'postalCode'),\n\t\t\tcountry: this.#str(mutable, 'country'),\n\t\t\tstateOrProvince: this.#str(mutable, 'stateOrProvince'),\n\t\t\thomePhone: this.#str(mutable, 'homePhone'),\n\t\t\tmobilePhone: this.#str(mutable, 'mobilePhone'),\n\t\t\tbusinessPhone: this.#str(mutable, 'businessPhone'),\n\t\t\tbusinessFax: this.#str(mutable, 'businessFax'),\n\t\t\tbusinessHomePage: this.#str(mutable, 'businessHomePage'),\n\t\t\tnamePrefix: this.#str(mutable, 'namePrefix'),\n\t\t\thomeAddressCity: this.#str(mutable, 'homeAddressCity'),\n\t\t\t// appointment / calendar properties\n\t\t\tappointmentStart: this.#str(mutable, 'appointmentStart'),\n\t\t\tappointmentEnd: this.#str(mutable, 'appointmentEnd'),\n\t\t\tclipStart: this.#str(mutable, 'clipStart'),\n\t\t\tclipEnd: this.#str(mutable, 'clipEnd'),\n\t\t\ttimeZoneDescription: this.#str(mutable, 'timeZoneDescription'),\n\t\t\tappointmentLocation: this.#str(mutable, 'appointmentLocation'),\n\t\t\tappointmentOldLocation: this.#str(mutable, 'appointmentOldLocation'),\n\t\t\tglobalAppointmentId: this.#str(mutable, 'globalAppointmentId'),\n\t\t\t// PidLid - common\n\t\t\tvotingResponse: this.#str(mutable, 'votingResponse'),\n\t\t\tinternetAccountName: this.#str(mutable, 'internetAccountName'),\n\t\t\t// PidLid - address\n\t\t\tyomiFirstName: this.#str(mutable, 'yomiFirstName'),\n\t\t\tyomiLastName: this.#str(mutable, 'yomiLastName'),\n\t\t\tyomiCompanyName: this.#str(mutable, 'yomiCompanyName'),\n\t\t\tprimaryEmailAddress: this.#str(mutable, 'primaryEmailAddress'),\n\t\t\tprimaryEmailDisplayName: this.#str(mutable, 'primaryEmailDisplayName'),\n\t\t\tprimaryEmailOriginalDisplayName: this.#str(mutable, 'primaryEmailOriginalDisplayName'),\n\t\t\tfileUnder: this.#str(mutable, 'fileUnder'),\n\t\t\tworkAddressCity: this.#str(mutable, 'workAddressCity'),\n\t\t\tworkAddressStreet: this.#str(mutable, 'workAddressStreet'),\n\t\t\tworkAddressState: this.#str(mutable, 'workAddressState'),\n\t\t\tworkAddressPostalCode: this.#str(mutable, 'workAddressPostalCode'),\n\t\t\tworkAddressCountry: this.#str(mutable, 'workAddressCountry'),\n\t\t\tworkAddressCountryCode: this.#str(mutable, 'workAddressCountryCode'),\n\t\t\taddressCountryCode: this.#str(mutable, 'addressCountryCode'),\n\t\t\tcontactWebPage: this.#str(mutable, 'contactWebPage'),\n\t\t\tworkAddress: this.#str(mutable, 'workAddress'),\n\t\t\tinstantMessagingAddress: this.#str(mutable, 'instantMessagingAddress'),\n\t\t\tfax1AddressType: this.#str(mutable, 'fax1AddressType'),\n\t\t\tfax1EmailAddress: this.#str(mutable, 'fax1EmailAddress'),\n\t\t\tfax1OriginalDisplayName: this.#str(mutable, 'fax1OriginalDisplayName'),\n\t\t\tfax2AddressType: this.#str(mutable, 'fax2AddressType'),\n\t\t\tfax2EmailAddress: this.#str(mutable, 'fax2EmailAddress'),\n\t\t\tfax2OriginalDisplayName: this.#str(mutable, 'fax2OriginalDisplayName'),\n\t\t\tfax3AddressType: this.#str(mutable, 'fax3AddressType'),\n\t\t\tfax3EmailAddress: this.#str(mutable, 'fax3EmailAddress'),\n\t\t\tfax3OriginalDisplayName: this.#str(mutable, 'fax3OriginalDisplayName'),\n\t\t}\n\t}\n\n\t#processDirectory(entry: MSGDirectoryEntry, fields: MSGMutableFieldData, subClass: string): void {\n\t\tconst children = entry.children\n\t\tif (children === undefined) return\n\n\t\t// Process sub-folders first\n\t\tfor (let i = 0; i < children.length; i++) {\n\t\t\tconst childIndex = children[i]\n\t\t\tconst child = this.#properties[childIndex]\n\t\t\tif (child === undefined) continue\n\n\t\t\tif (child.type === MSG_TYPE_DIRECTORY) {\n\t\t\t\tthis.#processSubDirectory(child, childIndex, fields)\n\t\t\t}\n\t\t}\n\n\t\t// Process document streams\n\t\tfor (let i = 0; i < children.length; i++) {\n\t\t\tconst childIndex = children[i]\n\t\t\tconst child = this.#properties[childIndex]\n\t\t\tif (child === undefined) continue\n\n\t\t\tif (child.type === MSG_TYPE_DOCUMENT) {\n\t\t\t\tif (child.name.indexOf(MSG_PREFIX_DOCUMENT) === 0) {\n\t\t\t\t\tthis.#processDocument(child, childIndex, fields)\n\t\t\t\t} else if (child.name === '__properties_version1.0') {\n\t\t\t\t\tif (subClass === 'recip' || subClass === 'attachment' || subClass === 'sub') {\n\t\t\t\t\t\tthis.#processPropertyStream(child, 8, fields)\n\t\t\t\t\t} else if (subClass === 'root') {\n\t\t\t\t\t\tthis.#processPropertyStream(child, 32, fields)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t#processSubDirectory(\n\t\tchild: MSGDirectoryEntry,\n\t\tchildIndex: number,\n\t\tfields: MSGMutableFieldData,\n\t): void {\n\t\tif (child.name.indexOf(MSG_PREFIX_ATTACHMENT) === 0) {\n\t\t\tconst attachmentField: MSGMutableFieldData = { kind: 'attachment' }\n\t\t\tif (fields.attachments === undefined) fields.attachments = []\n\t\t\tfields.attachments.push(attachmentField)\n\t\t\tthis.#processDirectory(child, attachmentField, 'attachment')\n\t\t} else if (child.name.indexOf(MSG_PREFIX_RECIPIENT) === 0) {\n\t\t\tconst recipientField: MSGMutableFieldData = { kind: 'recipient' }\n\t\t\tif (fields.recipients === undefined) fields.recipients = []\n\t\t\tfields.recipients.push(recipientField)\n\t\t\tthis.#processDirectory(child, recipientField, 'recip')\n\t\t} else if (child.name.indexOf(MSG_PREFIX_NAMEID) === 0) {\n\t\t\tthis.#processNameIdDirectory(child)\n\t\t} else {\n\t\t\tconst fieldType = this.#getDirectoryFieldType(child)\n\t\t\tif (fieldType === MSG_FIELD_DIR_TYPE_INNER_MSG) {\n\t\t\t\tconst innerFields: MSGMutableFieldData = {\n\t\t\t\t\tkind: 'msg',\n\t\t\t\t\tattachments: [],\n\t\t\t\t\trecipients: [],\n\t\t\t\t}\n\t\t\t\tthis.#processDirectory(child, innerFields, 'sub')\n\t\t\t\tfields.innerMSGContentFields = innerFields\n\t\t\t\tfields.innerMSGContent = true\n\t\t\t\tfields.folderId = childIndex\n\t\t\t\tthis.#innerMSGBurners[childIndex] = () => this.#burnFolder(child, true, true)\n\t\t\t}\n\t\t}\n\t}\n\n\t#getDirectoryFieldType(entry: MSGDirectoryEntry): string {\n\t\tconst value = entry.name.substring(12).toLowerCase()\n\t\treturn value.substring(4, 8)\n\t}\n\n\t#processDocument(\n\t\tentry: MSGDirectoryEntry,\n\t\tentryIndex: number,\n\t\tfields: MSGMutableFieldData,\n\t): void {\n\t\tconst value = entry.name.substring(12).toLowerCase()\n\t\tconst fieldClass = value.substring(0, 4)\n\t\tconst fieldType = value.substring(4, 8)\n\n\t\tif (fieldClass === MSG_FIELD_CLASS_ATTACHMENT_DATA) {\n\t\t\tfields.dataId = entryIndex\n\t\t\tfields.contentLength = entry.sizeBlock\n\t\t\treturn\n\t\t}\n\n\t\tconst data = this.#readEntry(entry)\n\t\tthis.#decodeAndAssign(fieldClass, fieldType, data, fields, false)\n\t}\n\n\t#processPropertyStream(\n\t\tentry: MSGDirectoryEntry,\n\t\theaderSize: number,\n\t\tfields: MSGMutableFieldData,\n\t): void {\n\t\tconst data = this.#readEntry(entry)\n\t\tif (data.length <= headerSize) return\n\n\t\tconst propView = new DataView(\n\t\t\tdata.buffer,\n\t\t\tdata.byteOffset + headerSize,\n\t\t\tdata.length - headerSize,\n\t\t)\n\t\tlet offset = 0\n\n\t\twhile (offset + 16 <= propView.byteLength) {\n\t\t\tconst propertyTag = propView.getUint32(offset, true)\n\t\t\tif (propertyTag === 0) break\n\t\t\t// skip flags (4 bytes)\n\t\t\toffset += 8\n\n\t\t\tconst valueBytes = new Uint8Array(data.buffer, data.byteOffset + headerSize + offset, 8)\n\t\t\toffset += 8\n\n\t\t\tconst fieldClass = toHexLower((propertyTag >>> 16) & 0xffff, 4)\n\t\t\tconst fieldType = toHexLower(propertyTag & 0xffff, 4)\n\n\t\t\tthis.#decodeAndAssign(fieldClass, fieldType, valueBytes, fields, true)\n\t\t}\n\t}\n\n\t#decodeAndAssign(\n\t\tfieldClass: string,\n\t\tfieldType: string,\n\t\tdata: Uint8Array,\n\t\tfields: MSGMutableFieldData,\n\t\tinsideProps: boolean,\n\t): void {\n\t\tconst fullTag = `${fieldClass}${fieldType}`\n\t\tlet key: string | undefined =\n\t\t\tMSG_FIELD_FULL_NAME_MAPPING[fullTag] ?? MSG_FIELD_NAME_MAPPING[fieldClass]\n\n\t\tconst classValue = parseInt(fieldClass, 16)\n\t\tif (!Number.isNaN(classValue) && classValue >= 0x8000) {\n\t\t\tconst keyed = this.#privatePidToKeyed[classValue]\n\t\t\tif (keyed !== undefined) {\n\t\t\t\tif (keyed.useName) {\n\t\t\t\t\tkey = keyed.name\n\t\t\t\t} else if (keyed.propertySet !== undefined && keyed.propertyLid !== undefined) {\n\t\t\t\t\tconst resolved = this.#resolvePidLid(keyed.propertySet, keyed.propertyLid)\n\t\t\t\t\tif (resolved !== undefined) {\n\t\t\t\t\t\tkey = resolved\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst decodeAs = MSG_FIELD_TYPE_MAPPING[fieldType]\n\t\tlet value: unknown = data\n\n\t\tif (decodeAs === 'string') {\n\t\t\tvalue = removeTrailingNull(readANSIString(data, this.#options.encoding))\n\t\t\tif (insideProps) key = undefined\n\t\t} else if (decodeAs === 'unicode') {\n\t\t\tconst view = new DataView(data.buffer, data.byteOffset, data.length)\n\t\t\tvalue = removeTrailingNull(readUTF16String(view, 0, Math.floor(data.length / 2)))\n\t\t\tif (insideProps) key = undefined\n\t\t} else if (decodeAs === 'binary') {\n\t\t\tif (insideProps) key = undefined\n\t\t} else if (decodeAs === 'integer') {\n\t\t\tif (data.length >= 4) {\n\t\t\t\tconst dv = new DataView(data.buffer, data.byteOffset, data.length)\n\t\t\t\tvalue = dv.getUint32(0, true)\n\t\t\t}\n\t\t} else if (decodeAs === 'boolean') {\n\t\t\tif (data.length >= 2) {\n\t\t\t\tconst dv = new DataView(data.buffer, data.byteOffset, data.length)\n\t\t\t\tvalue = dv.getUint16(0, true) !== 0\n\t\t\t}\n\t\t} else if (decodeAs === 'time') {\n\t\t\tif (data.length >= 8) {\n\t\t\t\tconst dv = new DataView(data.buffer, data.byteOffset, data.length)\n\t\t\t\tconst lo = dv.getUint32(0, true)\n\t\t\t\tconst hi = dv.getUint32(4, true)\n\t\t\t\tvalue = fileTimeToUTCString(lo, hi)\n\t\t\t}\n\t\t}\n\n\t\t// Resolve recipientRole from integer to string\n\t\tif (key === 'recipientRole' && typeof value === 'number') {\n\t\t\tif (value === MSG_MAPI_RECIPIENT_TO) value = 'to' satisfies MSGRecipientRole\n\t\t\telse if (value === MSG_MAPI_RECIPIENT_CC) value = 'cc' satisfies MSGRecipientRole\n\t\t\telse if (value === MSG_MAPI_RECIPIENT_BCC) value = 'bcc' satisfies MSGRecipientRole\n\t\t}\n\n\t\tif (key !== undefined) {\n\t\t\tfields[key] = value\n\t\t}\n\t}\n\n\t#resolvePidLid(propertySet: string, propertyLid: number): string | undefined {\n\t\tconst setMapping = MSG_PIDLID_MAPPING[propertySet]\n\t\tif (setMapping === undefined) return undefined\n\t\treturn setMapping[propertyLid]\n\t}\n\n\t// === Named Property ID Resolution (__nameid_version1.0)\n\n\t#processNameIdDirectory(dirEntry: MSGDirectoryEntry): void {\n\t\tconst children = dirEntry.children\n\t\tif (children === undefined) return\n\n\t\tlet guidTable: Uint8Array | undefined\n\t\tlet entryTable: Uint8Array | undefined\n\t\tlet stringTable: Uint8Array | undefined\n\n\t\tfor (let i = 0; i < children.length; i++) {\n\t\t\tconst childIndex = children[i]\n\t\t\tconst child = this.#properties[childIndex]\n\t\t\tif (child === undefined || child.type !== MSG_TYPE_DOCUMENT) continue\n\t\t\tif (child.name.indexOf(MSG_PREFIX_DOCUMENT) !== 0) continue\n\n\t\t\tconst value = child.name.substring(12).toLowerCase()\n\t\t\tconst fieldClass = value.substring(0, 4)\n\t\t\tconst fieldType = value.substring(4, 8)\n\n\t\t\tif (fieldClass === '0002' && fieldType === '0102') {\n\t\t\t\tguidTable = this.#readEntry(child)\n\t\t\t} else if (fieldClass === '0003' && fieldType === '0102') {\n\t\t\t\tentryTable = this.#readEntry(child)\n\t\t\t} else if (fieldClass === '0004' && fieldType === '0102') {\n\t\t\t\tstringTable = this.#readEntry(child)\n\t\t\t}\n\t\t}\n\n\t\tif (guidTable === undefined || entryTable === undefined || stringTable === undefined) return\n\n\t\tthis.#parseEntryStream(entryTable, guidTable, stringTable)\n\t}\n\n\t#parseEntryStream(entryTable: Uint8Array, guidTable: Uint8Array, stringTable: Uint8Array): void {\n\t\tconst view = new DataView(entryTable.buffer, entryTable.byteOffset, entryTable.length)\n\t\tconst entryCount = Math.floor(entryTable.length / 8)\n\n\t\tfor (let i = 0; i < entryCount; i++) {\n\t\t\tconst offset = i * 8\n\t\t\tconst nameIdOrStringOffset = view.getUint32(offset, true)\n\t\t\tconst indexAndKind = view.getUint16(offset + 4, true)\n\t\t\tconst propertyIndex = view.getUint16(offset + 6, true)\n\n\t\t\tconst guidIndex = (indexAndKind >>> 1) & 0x7fff\n\t\t\tconst isStringProperty = (nameIdOrStringOffset & 1) !== 0\n\n\t\t\tif (isStringProperty) {\n\t\t\t\tconst strView = new DataView(stringTable.buffer, stringTable.byteOffset, stringTable.length)\n\t\t\t\tconst strOffset = nameIdOrStringOffset >>> 0\n\t\t\t\tif (strOffset + 4 <= stringTable.length) {\n\t\t\t\t\tconst numTextBytes = strView.getUint32(strOffset, true)\n\t\t\t\t\tconst charCount = Math.floor(numTextBytes / 2)\n\t\t\t\t\tif (strOffset + 4 + numTextBytes <= stringTable.length) {\n\t\t\t\t\t\tconst name = readUTF16String(strView, strOffset + 4, charCount)\n\t\t\t\t\t\tthis.#privatePidToKeyed[0x8000 | propertyIndex] = {\n\t\t\t\t\t\t\tuseName: true,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlet propertySet: string | undefined\n\t\t\t\tif (guidIndex === 1) {\n\t\t\t\t\tpropertySet = '00020328-0000-0000-c000-000000000046'\n\t\t\t\t} else if (guidIndex === 2) {\n\t\t\t\t\tpropertySet = '00020329-0000-0000-c000-000000000046'\n\t\t\t\t} else {\n\t\t\t\t\tconst guidOffset = 16 * (guidIndex - 3)\n\t\t\t\t\tif (guidOffset >= 0 && guidOffset + 16 <= guidTable.length) {\n\t\t\t\t\t\tpropertySet = msftUUIDStringify(guidTable, guidOffset)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (propertySet !== undefined) {\n\t\t\t\t\tthis.#privatePidToKeyed[0x8000 | propertyIndex] = {\n\t\t\t\t\t\tuseName: false,\n\t\t\t\t\t\tpropertySet,\n\t\t\t\t\t\tpropertyLid: nameIdOrStringOffset,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// === Burner (CFB reconstitution for embedded MSG)\n\n\t#burnFolder(\n\t\tfolder: MSGDirectoryEntry,\n\t\tpadTopLevelPropertyStream: boolean,\n\t\tincludeRootNameId: boolean,\n\t): Uint8Array {\n\t\tconst entries: MSGBurnerEntry[] = [\n\t\t\t{\n\t\t\t\tname: 'Root Entry',\n\t\t\t\ttype: MSG_TYPE_ROOT,\n\t\t\t\tchildren: [],\n\t\t\t\tlength: 0,\n\t\t\t},\n\t\t]\n\t\tthis.#registerBurnerFolder(entries, 0, folder, padTopLevelPropertyStream, includeRootNameId)\n\t\tconst burner = new MSGBurner()\n\t\treturn burner.burn(entries)\n\t}\n\n\t#registerBurnerFolder(\n\t\tentries: MSGBurnerEntry[],\n\t\tparentIndex: number,\n\t\tfolder: MSGDirectoryEntry,\n\t\tpadPropertyStream: boolean,\n\t\tincludeRootNameId: boolean,\n\t): void {\n\t\tconst children = folder.children\n\t\tif (children === undefined) return\n\n\t\tconst parentChildren = entries[parentIndex].children\n\t\tif (parentChildren === undefined) return\n\n\t\t// Register document streams\n\t\tfor (let i = 0; i < children.length; i++) {\n\t\t\tconst childIndex = children[i]\n\t\t\tconst child = this.#properties[childIndex]\n\t\t\tif (child === undefined || child.type !== MSG_TYPE_DOCUMENT) continue\n\n\t\t\tlet provider = () => this.#readEntry(child)\n\t\t\tlet length = child.sizeBlock\n\n\t\t\t// Embedded MSG storages use the sub-message property stream layout.\n\t\t\t// When promoting one to a standalone Root Entry, the top-level\n\t\t\t// __properties_version1.0 stream needs 8 bytes inserted at offset 24.\n\t\t\tif (padPropertyStream && child.name === '__properties_version1.0') {\n\t\t\t\tconst originalProvider = provider\n\t\t\t\tprovider = () => {\n\t\t\t\t\tconst src = originalProvider()\n\t\t\t\t\tconst dst = new Uint8Array(src.length + 8)\n\t\t\t\t\tdst.set(src.subarray(0, 24), 0)\n\t\t\t\t\tdst.set(src.subarray(24), 32)\n\t\t\t\t\treturn dst\n\t\t\t\t}\n\t\t\t\tlength = length + 8\n\t\t\t}\n\n\t\t\tconst subIndex = entries.length\n\t\t\tparentChildren.push(subIndex)\n\t\t\tentries.push({\n\t\t\t\tname: child.name,\n\t\t\t\ttype: MSG_TYPE_DOCUMENT,\n\t\t\t\tbinaryProvider: provider,\n\t\t\t\tlength,\n\t\t\t})\n\t\t}\n\n\t\t// Include root __nameid_version1.0 when rebuilding an embedded MSG as a\n\t\t// standalone file, because the embedded storage does not carry it itself.\n\t\tif (includeRootNameId) {\n\t\t\tconst rootProp = this.#properties[0]\n\t\t\tif (rootProp !== undefined && rootProp.children !== undefined) {\n\t\t\t\tfor (let i = 0; i < rootProp.children.length; i++) {\n\t\t\t\t\tconst rootChildIndex = rootProp.children[i]\n\t\t\t\t\tconst rootChild = this.#properties[rootChildIndex]\n\t\t\t\t\tif (\n\t\t\t\t\t\trootChild !== undefined &&\n\t\t\t\t\t\trootChild.type === MSG_TYPE_DIRECTORY &&\n\t\t\t\t\t\trootChild.name === MSG_PREFIX_NAMEID\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst subIndex = entries.length\n\t\t\t\t\t\tparentChildren.push(subIndex)\n\t\t\t\t\t\tentries.push({\n\t\t\t\t\t\t\tname: rootChild.name,\n\t\t\t\t\t\t\ttype: MSG_TYPE_DIRECTORY,\n\t\t\t\t\t\t\tchildren: [],\n\t\t\t\t\t\t\tlength: 0,\n\t\t\t\t\t\t})\n\t\t\t\t\t\tthis.#registerBurnerFolder(entries, subIndex, rootChild, false, false)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Register sub-directories\n\t\tfor (let i = 0; i < children.length; i++) {\n\t\t\tconst childIndex = children[i]\n\t\t\tconst child = this.#properties[childIndex]\n\t\t\tif (child === undefined || child.type !== MSG_TYPE_DIRECTORY) continue\n\n\t\t\tconst subIndex = entries.length\n\t\t\tparentChildren.push(subIndex)\n\t\t\tentries.push({\n\t\t\t\tname: child.name,\n\t\t\t\ttype: MSG_TYPE_DIRECTORY,\n\t\t\t\tchildren: [],\n\t\t\t\tlength: 0,\n\t\t\t})\n\t\t\tthis.#registerBurnerFolder(entries, subIndex, child, false, false)\n\t\t}\n\t}\n}\n","/**\n * EmailParser\n *\n * Parses .eml (RFC 2822 / MIME) and .msg (Outlook binary) files\n * into structured EmailMessage objects. Zero dependencies — uses\n * a pure-ES MIME parser for .eml and the built-in MSGReader for .msg.\n */\n\nimport type {\n\tEmailParserInterface,\n\tEmailParserOptions,\n\tEmailInput,\n\tResult,\n\tEmailChain,\n} from './types.js'\nimport {\n\tdetectFormat,\n\tparseMIMEPart,\n\textractMessage,\n\textractMessageFromMSG,\n\tisMSGFile,\n\tdecodeUTF8,\n\tsuccess,\n\tfailure,\n} from './helpers.js'\nimport { MSGError, isMSGError } from './errors.js'\nimport { MSGReader } from './MSGReader.js'\n\n// === EmailParser\n\n/**\n * Parses raw .eml or .msg file bytes into a structured {@link EmailChain}.\n * Synchronous and dependency-free: format detection falls back to sniffing\n * the CFB magic header when neither `name` nor `mime` resolves it, and every\n * parse failure is contained into a `Result` rather than thrown.\n *\n * @example\n * ```ts\n * import { createEmailParser, isSuccess } from '@src/core'\n *\n * const parser = createEmailParser()\n * const result = parser.parse({ bytes, name: 'message.eml' })\n * if (isSuccess(result)) {\n * \tconst { messages } = result.value\n * \tconsole.log(messages[0].text)\n * \tconsole.log(messages[0].attachments)\n * }\n * ```\n */\nexport class EmailParser implements EmailParserInterface {\n\treadonly #options: EmailParserOptions\n\n\tconstructor(options: EmailParserOptions = {}) {\n\t\tthis.#options = { ...options }\n\t}\n\n\t/**\n\t * Parse raw email bytes into a structured chain.\n\t *\n\t * @param input - Raw bytes plus optional name/MIME hints\n\t * @returns A {@link Success} wrapping the parsed {@link EmailChain}, or a\n\t * {@link Failure} wrapping an {@link MSGError} (code `UNSUPPORTED` when\n\t * the format cannot be determined, `MALFORMED` when parsing fails)\n\t *\n\t * @example\n\t * ```ts\n\t * const result = parser.parse({ bytes, name: 'message.msg' })\n\t * ```\n\t */\n\tparse(input: EmailInput): Result<EmailChain, MSGError> {\n\t\ttry {\n\t\t\tconst format =\n\t\t\t\tdetectFormat(input.name, input.mime) ??\n\t\t\t\t(isMSGFile(new DataView(input.bytes.buffer, input.bytes.byteOffset, input.bytes.byteLength))\n\t\t\t\t\t? 'msg'\n\t\t\t\t\t: undefined)\n\n\t\t\tif (format === undefined) {\n\t\t\t\treturn failure(\n\t\t\t\t\tnew MSGError(\n\t\t\t\t\t\t'UNSUPPORTED',\n\t\t\t\t\t\t`\"${input.name ?? 'input'}\" — only .eml and .msg files are supported`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: input.name,\n\t\t\t\t\t\t\tmime: input.mime,\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (format === 'msg') {\n\t\t\t\tconst reader = new MSGReader(input.bytes, { encoding: this.#options.encoding })\n\t\t\t\tconst message = extractMessageFromMSG(reader)\n\t\t\t\treturn success({ format, messages: [message] })\n\t\t\t}\n\n\t\t\tconst text = decodeUTF8(input.bytes)\n\t\t\tconst root = parseMIMEPart(text)\n\t\t\tconst message = extractMessage(root)\n\t\t\treturn success({ format, messages: [message] })\n\t\t} catch (cause) {\n\t\t\tif (isMSGError(cause)) return failure(cause)\n\t\t\tif (cause instanceof Error) return failure(new MSGError('MALFORMED', cause.message))\n\t\t\treturn failure(new MSGError('MALFORMED', 'Failed to parse email input'))\n\t\t}\n\t}\n\n\t/**\n\t * Current parser configuration.\n\t *\n\t * @returns A copy of the configured {@link EmailParserOptions} — the\n\t * internal reference is never leaked\n\t */\n\tget options(): EmailParserOptions {\n\t\treturn { ...this.#options }\n\t}\n}\n","import type {\n\tMSGReaderInterface,\n\tMSGReaderOptions,\n\tMSGBurnerInterface,\n\tEmailParserInterface,\n\tEmailParserOptions,\n} from './types.js'\nimport { MSGReader } from './MSGReader.js'\nimport { MSGBurner } from './MSGBurner.js'\nimport { EmailParser } from './EmailParser.js'\n\n// === MSGReader\n\n/**\n * Create a new .msg file reader.\n *\n * @param buffer - Raw .msg file bytes\n * @param options - Optional reader configuration\n * @returns A working {@link MSGReaderInterface}\n *\n * @example\n * ```ts\n * import { createMSGReader } from '@src/core'\n *\n * const reader = createMSGReader(buffer)\n * const data = reader.parse()\n * console.log(data.kind)\n * ```\n */\nexport function createMSGReader(\n\tbuffer: ArrayBuffer | Uint8Array,\n\toptions?: MSGReaderOptions,\n): MSGReaderInterface {\n\treturn new MSGReader(buffer, options)\n}\n\n// === MSGBurner\n\n/**\n * Create a new CFB binary writer for reconstituting .msg files.\n *\n * @returns A working {@link MSGBurnerInterface}\n *\n * @example\n * ```ts\n * import { createMSGBurner } from '@src/core'\n *\n * const burner = createMSGBurner()\n * const binary = burner.burn(entries)\n * ```\n */\nexport function createMSGBurner(): MSGBurnerInterface {\n\treturn new MSGBurner()\n}\n\n// === EmailParser\n\n/**\n * Create a new email file parser for .eml and .msg input.\n *\n * @param options - Optional parser configuration\n * @returns A working {@link EmailParserInterface}\n *\n * @example\n * ```ts\n * import { createEmailParser, isSuccess } from '@src/core'\n *\n * const parser = createEmailParser()\n * const result = parser.parse({ bytes, name: 'message.eml' })\n * if (isSuccess(result)) {\n * \tconsole.log(result.value.messages[0].subject)\n * }\n * ```\n */\nexport function createEmailParser(options?: EmailParserOptions): EmailParserInterface {\n\treturn new EmailParser(options)\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orkestrel/msg",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A zero-dependency Outlook .msg (CFB/OLE2) and .eml (RFC 2822/MIME) email parser — extracts headers, bodies, recipients, and attachments into typed structures, with .msg round-trip rebuild. Part of the @orkestrel line.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"attachments",
|
|
7
|
+
"cfb",
|
|
8
|
+
"email",
|
|
9
|
+
"eml",
|
|
10
|
+
"mime",
|
|
11
|
+
"msg",
|
|
12
|
+
"ole2",
|
|
13
|
+
"outlook",
|
|
14
|
+
"parser",
|
|
15
|
+
"typescript"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/orkestrel/msg#readme",
|
|
18
|
+
"bugs": "https://github.com/orkestrel/msg/issues",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/orkestrel/msg.git"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"main": "./dist/src/core/index.cjs",
|
|
31
|
+
"module": "./dist/src/core/index.js",
|
|
32
|
+
"types": "./dist/src/core/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./dist/src/core/index.d.ts",
|
|
37
|
+
"default": "./dist/src/core/index.js"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./dist/src/core/index.d.cts",
|
|
41
|
+
"default": "./dist/src/core/index.cjs"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"clean": "node -e \"try{require('node:fs').rmSync('dist',{recursive:true,force:true})}catch{}\"",
|
|
51
|
+
"copy": "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
|
|
52
|
+
"tmp:txt": "node -e \"const fs=require('node:fs'),p=require('node:path');function walk(d){for(const e of fs.readdirSync(d,{withFileTypes:true})){const f=p.join(d,e.name);if(e.isDirectory()){walk(f)}else if(!e.name.endsWith('.md')&&!e.name.endsWith('.txt')){const t=f+'.txt';if(!fs.existsSync(t)){fs.renameSync(f,t)}else{console.warn('Skipping '+f+' — target exists: '+t)}}}}try{walk('tmp')}catch(e){if(e.code!=='ENOENT')throw e}\"",
|
|
53
|
+
"lint": "oxlint --config .oxlintrc.json --fix .",
|
|
54
|
+
"check": "tsc --noEmit --project tsconfig.json",
|
|
55
|
+
"check:src": "npm run check:src:core",
|
|
56
|
+
"check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
|
|
57
|
+
"format": "oxfmt --config .oxfmtrc.json --write .",
|
|
58
|
+
"format:check": "oxfmt --config .oxfmtrc.json --check .",
|
|
59
|
+
"lint:check": "oxlint --config .oxlintrc.json .",
|
|
60
|
+
"test": "npm run test:src && npm run test:guides",
|
|
61
|
+
"test:src": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
|
|
62
|
+
"test:src:core": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
|
|
63
|
+
"test:guides": "vitest run --config vite.config.ts --reporter=dot --project guides",
|
|
64
|
+
"build": "npm run clean && npm run build:src",
|
|
65
|
+
"build:src": "npm run build:src:core",
|
|
66
|
+
"build:src:core": "vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts",
|
|
67
|
+
"prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run check:src && npm run build && npm test"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@microsoft/api-extractor": "^7.58.9",
|
|
71
|
+
"@orkestrel/guide": "^0.0.1",
|
|
72
|
+
"@types/node": "^26.1.1",
|
|
73
|
+
"oxfmt": "^0.58.0",
|
|
74
|
+
"oxlint": "^1.73.0",
|
|
75
|
+
"typescript": "^6.0.3",
|
|
76
|
+
"vite": "^8.1.4",
|
|
77
|
+
"vite-plugin-dts": "^5.0.3",
|
|
78
|
+
"vitest": "^4.1.10"
|
|
79
|
+
},
|
|
80
|
+
"engines": {
|
|
81
|
+
"node": ">=24"
|
|
82
|
+
}
|
|
83
|
+
}
|