@zone-eu/mailsplit
Advanced tools
+56
-0
@@ -12,8 +12,21 @@ /// <reference types="node" /> | ||
| export { | ||
| /** Splits raw message bytes into MIME node and content chunks. */ | ||
| Splitter, | ||
| /** Joins MIME node and content chunks back into raw message bytes. */ | ||
| Joiner, | ||
| /** Rewrites body content for MIME nodes selected by a filter function. */ | ||
| Rewriter, | ||
| /** Streams decoded body content for MIME nodes selected by a filter function. */ | ||
| Streamer, | ||
| /** Buffers byte input and emits larger Buffer chunks. */ | ||
| ChunkedPassthrough, | ||
| /** Parses, mutates, and rebuilds message header blocks. */ | ||
| Headers, | ||
| /** Represents one parsed MIME node and its header/body metadata. */ | ||
| MimeNode | ||
@@ -23,24 +36,67 @@ }; | ||
| export type { | ||
| /** Value that is either present as `T` or explicitly unavailable as `false`. */ | ||
| Maybe, | ||
| /** Single item in an IMAP-style MIME part number. */ | ||
| PartNumberItem, | ||
| /** IMAP-style path to a MIME part. */ | ||
| PartNumber, | ||
| /** Options passed through to libmime instances. */ | ||
| LibmimeOptions, | ||
| /** Configuration for `Splitter` and MIME node parsing. */ | ||
| SplitterOptions, | ||
| /** Configuration for `ChunkedPassthrough`. */ | ||
| ChunkedPassthroughOptions, | ||
| /** Configuration for format=flowed decoding. */ | ||
| FlowedDecoderOptions, | ||
| /** Parsed raw header line with a normalized lookup key. */ | ||
| HeaderLine, | ||
| /** Decoded structured header value. */ | ||
| DecodedHeader, | ||
| /** MIME node shape emitted by `Splitter`. */ | ||
| MimeNode, | ||
| /** Data or body bytes emitted by `Splitter`. */ | ||
| MessageChunk, | ||
| /** Sentinel input used internally by rewriter/streamer transforms. */ | ||
| EmptyChunk, | ||
| /** Object emitted by `Splitter`. */ | ||
| SplitterChunk, | ||
| /** Object accepted by rewriter and streamer transforms. */ | ||
| RewriterInput, | ||
| /** Predicate used to select MIME nodes. */ | ||
| FilterFunc, | ||
| /** Error object that may include a Node-style string code. */ | ||
| ErrorWithCode, | ||
| /** Callback that resumes processing after a selected node stream ends. */ | ||
| ContinueCallback, | ||
| /** Content transform stream used for decoded or encoded node bodies. */ | ||
| ContentStream, | ||
| /** Decoder stream with an internal readable-state guard. */ | ||
| DecoderStream, | ||
| /** Internal splitter grouping state. */ | ||
| SplitterGroup, | ||
| /** Payload emitted with `Rewriter`'s `node` event. */ | ||
| RewriterNode, | ||
| /** Payload emitted with `Streamer`'s `node` event. */ | ||
| StreamerNode | ||
| } from './lib/types'; |
| import { Transform } from 'node:stream'; | ||
| import type { ChunkedPassthroughOptions } from './types'; | ||
| /** Transform stream that buffers byte input and emits larger Buffer chunks. */ | ||
| declare class ChunkedPassthrough extends Transform { | ||
| /** | ||
| * Creates a chunking passthrough transform that accepts Buffer input and emits Buffer chunks. | ||
| * | ||
| * @param options Optional chunk size configuration. | ||
| */ | ||
| constructor(options?: ChunkedPassthroughOptions); | ||
| /** | ||
| * Registers a listener for buffered byte chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each buffered Buffer chunk. | ||
| * @returns This passthrough instance. | ||
| */ | ||
| on(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Registers a one-time listener for the next buffered byte chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives the next buffered Buffer chunk. | ||
| * @returns This passthrough instance. | ||
| */ | ||
| once(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Adds a listener for buffered byte chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each buffered Buffer chunk. | ||
| * @returns This passthrough instance. | ||
| */ | ||
| addListener(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Prepends a listener for buffered byte chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each buffered Buffer chunk. | ||
| * @returns This passthrough instance. | ||
| */ | ||
| prependListener(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Emits a buffered byte chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param data Buffer chunk to emit. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'data', data: Buffer): boolean; | ||
@@ -11,0 +57,0 @@ } |
@@ -5,2 +5,5 @@ 'use strict'; | ||
| /** | ||
| * Transform stream that buffers byte input and emits larger Buffer chunks. | ||
| */ | ||
| class ChunkedPassthrough extends Transform { | ||
@@ -7,0 +10,0 @@ /** |
| import { Transform } from 'node:stream'; | ||
| import type { FlowedDecoderOptions } from './types'; | ||
| /** Transform stream that decodes `text/plain; format=flowed` content. */ | ||
| declare class FlowedDecoder extends Transform { | ||
| /** | ||
| * Creates a flowed text decoder that accepts encoded text bytes and emits decoded Buffer chunks. | ||
| * | ||
| * @param config Optional flowed text and charset decoding settings. | ||
| */ | ||
| constructor(config?: FlowedDecoderOptions); | ||
| /** | ||
| * Registers a listener for decoded flowed text bytes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives decoded Buffer chunks. | ||
| * @returns This decoder instance. | ||
| */ | ||
| on(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Registers a one-time listener for the next decoded flowed text chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives the next decoded Buffer chunk. | ||
| * @returns This decoder instance. | ||
| */ | ||
| once(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Adds a listener for decoded flowed text bytes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives decoded Buffer chunks. | ||
| * @returns This decoder instance. | ||
| */ | ||
| addListener(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Prepends a listener for decoded flowed text bytes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives decoded Buffer chunks. | ||
| * @returns This decoder instance. | ||
| */ | ||
| prependListener(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Emits a decoded flowed text chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param data Buffer chunk to emit. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'data', data: Buffer): boolean; | ||
@@ -11,0 +57,0 @@ } |
| 'use strict'; | ||
| // Helper class to rewrite nodes with specific mime type | ||
| // Helper class to decode format=flowed text nodes | ||
@@ -13,10 +13,9 @@ const Transform = require('stream').Transform; | ||
| /** | ||
| * Really bad "stream" transform to parse format=flowed content | ||
| * Transform stream that decodes text/plain format=flowed content. | ||
| * | ||
| * @constructor | ||
| * @param {FlowedDecoderOptions} [config] | ||
| * @param {FlowedDecoderOptions} [config] Flowed text and charset decoding settings. | ||
| */ | ||
| class FlowedDecoder extends Transform { | ||
| /** | ||
| * @param {FlowedDecoderOptions} [config] | ||
| * @param {FlowedDecoderOptions} [config] Flowed text and charset decoding settings. | ||
| */ | ||
@@ -23,0 +22,0 @@ constructor(config) { |
+93
-0
| import type { DecodedHeader, HeaderLine, LibmimeOptions } from './types'; | ||
| /** Mutable parser and builder for RFC-style message header blocks. */ | ||
| declare class Headers { | ||
| /** Whether header lines have been modified after construction. */ | ||
| changed: boolean; | ||
| /** Original unparsed header source, or `false` when constructed from parsed lines. */ | ||
| headers: string | Buffer | false; | ||
| /** Whether `headers` has been parsed into `lines`. */ | ||
| parsed: boolean; | ||
| /** Parsed header lines, or `false` until parsing occurs. */ | ||
| lines: HeaderLine[] | false; | ||
| /** MBOX `From ` prefix line, or `false` when absent. */ | ||
| mbox: string | false; | ||
| /** HTTP request prefix line, or `false` when absent. */ | ||
| http: string | false; | ||
| /** | ||
| * Creates a mutable header collection. | ||
| * | ||
| * @param headers Raw header bytes/string, already parsed header lines, or `false` for an empty collection. | ||
| * @param config Optional libmime configuration. | ||
| */ | ||
| constructor(headers?: string | Buffer | HeaderLine[] | false, config?: LibmimeOptions); | ||
| /** | ||
| * Checks whether at least one header with the requested key exists. | ||
| * | ||
| * @param key Header field name to find, case-insensitively. | ||
| * @returns `true` when the header exists. | ||
| */ | ||
| hasHeader(key: string): boolean; | ||
| /** | ||
| * Gets all raw header lines for a key. | ||
| * | ||
| * @param key Header field name to find, case-insensitively. | ||
| * @returns Full decoded header lines, including field names. | ||
| */ | ||
| get(key: string): string[]; | ||
| /** | ||
| * Gets all decoded structured header values for a key. | ||
| * | ||
| * @param key Header field name to decode, case-insensitively. | ||
| * @returns Decoded header entries with key and value fields. | ||
| */ | ||
| getDecoded(key: string): DecodedHeader[]; | ||
| /** | ||
| * Gets the first decoded header value for a key. | ||
| * | ||
| * @param key Header field name to find, case-insensitively. | ||
| * @returns Trimmed decoded value, or an empty string when the header is absent. | ||
| */ | ||
| getFirst(key: string): string; | ||
| /** | ||
| * Gets the mutable parsed header list. | ||
| * | ||
| * @returns Parsed header lines in message order. | ||
| */ | ||
| getList(): HeaderLine[]; | ||
| /** | ||
| * Adds a folded header line. | ||
| * | ||
| * @param key Header field name to add. | ||
| * @param value Header value; `undefined` leaves the collection unchanged. | ||
| * @param index Insertion index, where omitted or less than 1 inserts at the top. | ||
| * @returns Nothing. | ||
| */ | ||
| add(key: string, value?: string | number | Buffer, index?: number): void; | ||
| /** | ||
| * Adds a preformatted header line. | ||
| * | ||
| * @param key Header field name used for normalized lookup. | ||
| * @param line Full header line to insert; falsy values leave the collection unchanged. | ||
| * @param index Insertion index, where omitted or less than 1 inserts at the top. | ||
| * @returns Nothing. | ||
| */ | ||
| addFormatted(key: string, line?: string | Buffer | false, index?: number): void; | ||
| /** | ||
| * Removes all headers matching a key. | ||
| * | ||
| * @param key Header field name to remove, case-insensitively. | ||
| * @returns Nothing. | ||
| */ | ||
| remove(key: string): void; | ||
| /** | ||
| * Replaces matching headers with a new folded header value. | ||
| * | ||
| * @param key Header field name to update. | ||
| * @param value Header value to write; `undefined` removes matching values without adding a replacement. | ||
| * @param relativeIndex Optional zero-based index among headers with the same key. | ||
| * @returns Nothing. | ||
| */ | ||
| update(key: string, value?: string | number | Buffer, relativeIndex?: number): void; | ||
| /** | ||
| * Builds a raw header block. | ||
| * | ||
| * @param lineEnd Line ending to use when rebuilding changed headers; defaults to CRLF. | ||
| * @returns Header bytes ending with an empty header/body separator line. | ||
| */ | ||
| build(lineEnd?: string | false): Buffer; | ||
@@ -22,0 +115,0 @@ } |
+4
-4
@@ -12,9 +12,9 @@ 'use strict'; | ||
| /** | ||
| * Class Headers to parse and handle message headers. Headers instance allows to | ||
| * check existing, delete or add new headers | ||
| * Parses and builds message headers. A Headers instance allows callers to | ||
| * inspect, delete, update, and add header lines. | ||
| */ | ||
| class Headers { | ||
| /** | ||
| * @param {string | Buffer | HeaderLine[] | false} [headers] | ||
| * @param {LibmimeOptions} [config] | ||
| * @param {string | Buffer | HeaderLine[] | false} [headers] Raw header source or already parsed lines. | ||
| * @param {LibmimeOptions} [config] Optional libmime configuration. | ||
| */ | ||
@@ -21,0 +21,0 @@ constructor(headers, config) { |
| import { Transform } from 'node:stream'; | ||
| /** Transform stream that joins splitter objects back into raw email bytes. */ | ||
| declare class MessageJoiner extends Transform { | ||
| /** | ||
| * Creates a joiner that accepts splitter objects and emits Buffer chunks. | ||
| */ | ||
| constructor(); | ||
| /** | ||
| * Registers a listener for generated message bytes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each generated Buffer chunk. | ||
| * @returns This joiner instance. | ||
| */ | ||
| on(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Registers a one-time listener for generated message bytes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives the next generated Buffer chunk. | ||
| * @returns This joiner instance. | ||
| */ | ||
| once(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Adds a listener for generated message bytes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each generated Buffer chunk. | ||
| * @returns This joiner instance. | ||
| */ | ||
| addListener(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Prepends a listener for generated message bytes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each generated Buffer chunk. | ||
| * @returns This joiner instance. | ||
| */ | ||
| prependListener(event: 'data', listener: (data: Buffer) => void): this; | ||
| /** | ||
| * Emits a generated message byte chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param data Buffer chunk to emit. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'data', data: Buffer): boolean; | ||
@@ -10,0 +54,0 @@ } |
@@ -7,3 +7,9 @@ 'use strict'; | ||
| /** | ||
| * Transform stream that joins splitter objects back into raw message bytes. | ||
| */ | ||
| class MessageJoiner extends Transform { | ||
| /** | ||
| * Creates a joiner that accepts splitter objects and emits Buffer chunks. | ||
| */ | ||
| constructor() { | ||
@@ -10,0 +16,0 @@ let options = { |
| import { Transform } from 'node:stream'; | ||
| import type { SplitterChunk, SplitterOptions } from './types'; | ||
| /** Transform stream that splits raw email bytes into MIME node and content chunks. */ | ||
| declare class MessageSplitter extends Transform { | ||
| /** | ||
| * Creates a splitter that accepts Buffer input and emits `SplitterChunk` objects. | ||
| * | ||
| * @param config Optional parser limits and embedded-message behavior. | ||
| */ | ||
| constructor(config?: SplitterOptions); | ||
| /** | ||
| * Registers a listener for parsed splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each parsed MIME node, data chunk, or body chunk. | ||
| * @returns This splitter instance. | ||
| */ | ||
| on(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Registers a one-time listener for the next parsed splitter chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives the next parsed MIME node, data chunk, or body chunk. | ||
| * @returns This splitter instance. | ||
| */ | ||
| once(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Adds a listener for parsed splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each parsed MIME node, data chunk, or body chunk. | ||
| * @returns This splitter instance. | ||
| */ | ||
| addListener(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Prepends a listener for parsed splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each parsed MIME node, data chunk, or body chunk. | ||
| * @returns This splitter instance. | ||
| */ | ||
| prependListener(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Emits a parsed splitter chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param data MIME node, data chunk, or body chunk to emit. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'data', data: SplitterChunk): boolean; | ||
@@ -11,0 +57,0 @@ } |
@@ -19,2 +19,5 @@ 'use strict'; | ||
| /** | ||
| * Transform stream that splits raw email bytes into MIME node and content chunks. | ||
| */ | ||
| class MessageSplitter extends Transform { | ||
@@ -63,3 +66,8 @@ /** | ||
| /** @param {MessageChunk} data */ | ||
| /** | ||
| * Removes a pending line break from body data that belongs to a following boundary. | ||
| * | ||
| * @param {MessageChunk} data Body chunk to adjust in place. | ||
| * @returns {void} | ||
| */ | ||
| let checkTrailingLinebreak = data => { | ||
@@ -93,2 +101,7 @@ if (data.type === 'body' && data.node.parentNode && data.value && data.value.length) { | ||
| /** | ||
| * Iterates the current input chunk line by line and emits parsed groups. | ||
| * | ||
| * @returns {void} | ||
| */ | ||
| let iterateData = () => { | ||
@@ -95,0 +108,0 @@ for (let len = chunk.length; i < len; i++) { |
+106
-0
| import type { ContentStream, MimeNode as MimeNodeShape, PartNumber, PartNumberItem, SplitterOptions } from './types'; | ||
| import type Headers = require('./headers'); | ||
| /** Parsed MIME node with mutable headers and content encoding helpers. */ | ||
| declare class MimeNode implements MimeNodeShape { | ||
| /** Discriminator identifying this chunk as a MIME node. */ | ||
| type: 'node'; | ||
| /** Whether this node is the root message node. */ | ||
| root: boolean; | ||
| /** Parent MIME node, or `false` for the root node. */ | ||
| parentNode: MimeNodeShape | false; | ||
| /** Boundary used by this multipart node, or `false` when not multipart. */ | ||
| _boundary: Buffer | false; | ||
| /** Boundary inherited from the parent multipart node, or `false` when absent. */ | ||
| _parentBoundary: Buffer | false; | ||
| /** Length, in bytes, of the raw header block collected for this node. */ | ||
| _headerlen: number; | ||
| /** Multipart subtype such as `mixed` or `alternative`, or `false` for leaf nodes. */ | ||
| multipart: string | false; | ||
| /** Content-Transfer-Encoding value, normalized to lower case, or `false` when absent. */ | ||
| encoding: string | false; | ||
| /** Parsed and mutable header collection, available after headers are parsed. */ | ||
| headers: Headers | false; | ||
| /** MIME content type such as `text/plain`, or `false` when unavailable. */ | ||
| contentType: string | false; | ||
| /** Charset parameter from Content-Type, or `false` when absent. */ | ||
| charset: string | false; | ||
| /** Content-Disposition value such as `inline` or `attachment`, or `false` when absent. */ | ||
| disposition: string | false; | ||
| /** Decoded filename from Content-Disposition or Content-Type parameters, or `false` when absent. */ | ||
| filename: string | false; | ||
| /** Whether this node is `text/*` with `format=flowed`. */ | ||
| flowed: boolean; | ||
| /** Whether flowed text uses `delsp=yes`. */ | ||
| delSp: boolean; | ||
| /** Splitter configuration used when parsing this node. */ | ||
| config: SplitterOptions; | ||
| /** Resolved IMAP-style part number for this node, or `false` before resolution. */ | ||
| partNr: PartNumber | false; | ||
| /** Number of child part numbers allocated by this node. */ | ||
| childPartNumbers: number; | ||
| /** Whether this node's content type is `message/rfc822`. */ | ||
| rfc822: boolean; | ||
| /** Whether an embedded `message/rfc822` node was parsed as a nested message. */ | ||
| messageNode?: boolean; | ||
| /** | ||
| * Creates a MIME node with empty header state. | ||
| * | ||
| * @param parentNode Parent node, or `false`/omitted for the root node. | ||
| * @param config Optional splitter and libmime configuration. | ||
| */ | ||
| constructor(parentNode?: MimeNodeShape | false, config?: SplitterOptions); | ||
| /** | ||
| * Builds the next child part number for this node. | ||
| * | ||
| * @param provided Optional explicit part number item to append. | ||
| * @returns Resolved MIME part number. | ||
| */ | ||
| getPartNr(provided?: PartNumberItem): PartNumber; | ||
| /** | ||
| * Appends one raw header line to this node while parsing. | ||
| * | ||
| * @param line Raw header line bytes; falsy values are ignored. | ||
| * @returns Nothing. | ||
| */ | ||
| addHeaderChunk(line?: Buffer | false): void; | ||
| /** | ||
| * Parses collected header bytes and populates MIME metadata fields. | ||
| * | ||
| * @returns Nothing. | ||
| */ | ||
| parseHeaders(): void; | ||
| /** | ||
| * Builds this node's header block. | ||
| * | ||
| * @returns Header bytes ending with an empty header/body separator line. | ||
| */ | ||
| getHeaders(): Buffer; | ||
| /** | ||
| * Sets or updates the Content-Type header value. | ||
| * | ||
| * @param contentType MIME content type to set; falsy keeps the current type. | ||
| * @returns Nothing. | ||
| */ | ||
| setContentType(contentType?: string | false): void; | ||
| /** | ||
| * Sets, updates, or removes the Content-Type charset parameter. | ||
| * | ||
| * @param charset Charset to set; falsy removes it when possible. | ||
| * @returns Nothing. | ||
| */ | ||
| setCharset(charset?: string | false): void; | ||
| /** | ||
| * Sets, updates, or removes the filename parameter. | ||
| * | ||
| * @param filename Filename to set; falsy removes it when possible. | ||
| * @returns Nothing. | ||
| */ | ||
| setFilename(filename?: string | false): void; | ||
| /** | ||
| * Creates a decoder stream for this node's transfer encoding. | ||
| * | ||
| * @returns Transform stream that outputs decoded content bytes. | ||
| */ | ||
| getDecoder(): ContentStream; | ||
| /** | ||
| * Creates an encoder stream and updates the Content-Transfer-Encoding header when needed. | ||
| * | ||
| * @param encoding Target transfer encoding; defaults to the node's current encoding. | ||
| * @returns Transform stream that outputs encoded content bytes. | ||
| */ | ||
| getEncoder(encoding?: string | false): ContentStream; | ||
@@ -36,0 +142,0 @@ } |
+5
-2
@@ -21,6 +21,9 @@ 'use strict'; | ||
| /** | ||
| * Parsed MIME node with mutable headers and transfer-encoding helpers. | ||
| */ | ||
| class MimeNode { | ||
| /** | ||
| * @param {MimeNodeType | false} parentNode | ||
| * @param {SplitterOptions} [config] | ||
| * @param {MimeNodeType | false} parentNode Parent node, or false for the root node. | ||
| * @param {SplitterOptions} [config] Splitter and libmime configuration. | ||
| */ | ||
@@ -27,0 +30,0 @@ constructor(parentNode, config) { |
| import { Transform } from 'node:stream'; | ||
| import type { FilterFunc, RewriterNode, SplitterChunk } from './types'; | ||
| /** Transform stream that replaces the body content of selected MIME nodes. */ | ||
| declare class NodeRewriter extends Transform { | ||
| /** | ||
| * Creates a node rewriter that accepts splitter chunks and emits rewritten splitter chunks. | ||
| * | ||
| * @param filterFunc Predicate that selects MIME nodes to rewrite. | ||
| * @param rewriteAction Optional compatibility hook stored on the instance; consumers usually handle the `node` event. | ||
| */ | ||
| constructor(filterFunc: FilterFunc, rewriteAction?: Function); | ||
| /** | ||
| * Registers a listener for rewritten splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| on(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Registers a listener for selected nodes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives decoder and encoder streams for a selected node. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| on(event: 'node', listener: (data: RewriterNode) => void): this; | ||
| /** | ||
| * Registers a one-time listener for the next rewritten splitter chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives the next outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| once(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Registers a one-time listener for the next selected node. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives decoder and encoder streams for the next selected node. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| once(event: 'node', listener: (data: RewriterNode) => void): this; | ||
| /** | ||
| * Adds a listener for rewritten splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| addListener(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Adds a listener for selected nodes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives decoder and encoder streams for a selected node. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| addListener(event: 'node', listener: (data: RewriterNode) => void): this; | ||
| /** | ||
| * Prepends a listener for rewritten splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| prependListener(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Prepends a listener for selected nodes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives decoder and encoder streams for a selected node. | ||
| * @returns This rewriter instance. | ||
| */ | ||
| prependListener(event: 'node', listener: (data: RewriterNode) => void): this; | ||
| /** | ||
| * Emits a rewritten splitter chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param data MIME node, data chunk, or body chunk to emit. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'data', data: SplitterChunk): boolean; | ||
| /** | ||
| * Emits a selected-node payload. | ||
| * | ||
| * @param event Event name. | ||
| * @param data Selected node payload containing decoder and encoder streams. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'node', data: RewriterNode): boolean; | ||
@@ -16,0 +103,0 @@ } |
+23
-9
@@ -17,12 +17,12 @@ 'use strict'; | ||
| /** | ||
| * NodeRewriter Transform stream. Updates content for all nodes with specified mime type | ||
| * NodeRewriter Transform stream. Updates content for all nodes selected by the | ||
| * filter function. | ||
| * | ||
| * @constructor | ||
| * @param {FilterFunc} filterFunc Function to select nodes to rewrite | ||
| * @param {Function} [rewriteAction] Function to run with the node content | ||
| * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to rewrite it. | ||
| * @param {Function} [rewriteAction] Optional compatibility hook stored on the instance. | ||
| */ | ||
| class NodeRewriter extends Transform { | ||
| /** | ||
| * @param {FilterFunc} filterFunc | ||
| * @param {Function} [rewriteAction] | ||
| * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to rewrite it. | ||
| * @param {Function} [rewriteAction] Optional compatibility hook stored on the instance. | ||
| */ | ||
@@ -132,2 +132,7 @@ constructor(filterFunc, rewriteAction) { | ||
| /** | ||
| * Reads encoded replacement bytes and forwards them as body chunks. | ||
| * | ||
| * @returns {void | NodeJS.Immediate} | ||
| */ | ||
| let readFromEncoder = () => { | ||
@@ -207,5 +212,14 @@ decoder.$reading = true; | ||
| }); | ||
| flowDecoder.on('error', /** @param {Error} err */ err => { | ||
| decoder.emit('error', err); | ||
| }); | ||
| flowDecoder.on( | ||
| 'error', | ||
| /** | ||
| * Forwards flowed decoder errors to the replacement decoder. | ||
| * | ||
| * @param {Error} err Decoder error to forward. | ||
| * @returns {void} | ||
| */ | ||
| err => { | ||
| decoder.emit('error', err); | ||
| } | ||
| ); | ||
| flowDecoder.pipe(decoder); | ||
@@ -212,0 +226,0 @@ |
| import { Transform } from 'node:stream'; | ||
| import type { FilterFunc, SplitterChunk, StreamerNode } from './types'; | ||
| /** Transform stream that exposes decoded body streams for selected MIME nodes without replacing them. */ | ||
| declare class NodeStreamer extends Transform { | ||
| /** | ||
| * Creates a node streamer that accepts splitter chunks and passes them through unchanged. | ||
| * | ||
| * @param filterFunc Predicate that selects MIME nodes to stream. | ||
| * @param streamAction Optional compatibility hook stored on the instance; consumers usually handle the `node` event. | ||
| */ | ||
| constructor(filterFunc: FilterFunc, streamAction?: Function); | ||
| /** | ||
| * Registers a listener for passed-through splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This streamer instance. | ||
| */ | ||
| on(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Registers a listener for selected nodes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives a decoder stream and completion callback for a selected node. | ||
| * @returns This streamer instance. | ||
| */ | ||
| on(event: 'node', listener: (data: StreamerNode) => void): this; | ||
| /** | ||
| * Registers a one-time listener for the next passed-through splitter chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives the next outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This streamer instance. | ||
| */ | ||
| once(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Registers a one-time listener for the next selected node. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives a decoder stream and completion callback for the next selected node. | ||
| * @returns This streamer instance. | ||
| */ | ||
| once(event: 'node', listener: (data: StreamerNode) => void): this; | ||
| /** | ||
| * Adds a listener for passed-through splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This streamer instance. | ||
| */ | ||
| addListener(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Adds a listener for selected nodes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives a decoder stream and completion callback for a selected node. | ||
| * @returns This streamer instance. | ||
| */ | ||
| addListener(event: 'node', listener: (data: StreamerNode) => void): this; | ||
| /** | ||
| * Prepends a listener for passed-through splitter chunks. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives each outgoing MIME node, data chunk, or body chunk. | ||
| * @returns This streamer instance. | ||
| */ | ||
| prependListener(event: 'data', listener: (data: SplitterChunk) => void): this; | ||
| /** | ||
| * Prepends a listener for selected nodes. | ||
| * | ||
| * @param event Event name. | ||
| * @param listener Receives a decoder stream and completion callback for a selected node. | ||
| * @returns This streamer instance. | ||
| */ | ||
| prependListener(event: 'node', listener: (data: StreamerNode) => void): this; | ||
| /** | ||
| * Emits a passed-through splitter chunk. | ||
| * | ||
| * @param event Event name. | ||
| * @param data MIME node, data chunk, or body chunk to emit. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'data', data: SplitterChunk): boolean; | ||
| /** | ||
| * Emits a selected-node payload. | ||
| * | ||
| * @param event Event name. | ||
| * @param data Selected node payload containing decoder stream and completion callback. | ||
| * @returns `true` when the event had listeners. | ||
| */ | ||
| emit(event: 'node', data: StreamerNode): boolean; | ||
@@ -16,0 +103,0 @@ } |
+29
-10
| 'use strict'; | ||
| // Helper class to rewrite nodes with specific mime type | ||
| // Helper class to stream selected nodes by MIME metadata | ||
@@ -16,12 +16,12 @@ const Transform = require('stream').Transform; | ||
| /** | ||
| * NodeRewriter Transform stream. Updates content for all nodes with specified mime type | ||
| * NodeStreamer Transform stream. Exposes decoded content for nodes selected by | ||
| * the filter function while passing the original message through unchanged. | ||
| * | ||
| * @constructor | ||
| * @param {FilterFunc} filterFunc Function to select nodes to stream | ||
| * @param {Function} [streamAction] Function to run with the node content | ||
| * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to stream it. | ||
| * @param {Function} [streamAction] Optional compatibility hook stored on the instance. | ||
| */ | ||
| class NodeStreamer extends Transform { | ||
| /** | ||
| * @param {FilterFunc} filterFunc | ||
| * @param {Function} [streamAction] | ||
| * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to stream it. | ||
| * @param {Function} [streamAction] Optional compatibility hook stored on the instance. | ||
| */ | ||
@@ -93,2 +93,7 @@ constructor(filterFunc, streamAction) { | ||
| /** | ||
| * Resumes processing with the first chunk after the streamed node. | ||
| * | ||
| * @returns {void} | ||
| */ | ||
| let doContinue = () => { | ||
@@ -135,5 +140,14 @@ this.continue = false; | ||
| }); | ||
| flowDecoder.on('error', /** @param {Error} err */ err => { | ||
| decoder.emit('error', err); | ||
| }); | ||
| flowDecoder.on( | ||
| 'error', | ||
| /** | ||
| * Forwards flowed decoder errors to the output decoder. | ||
| * | ||
| * @param {Error} err Decoder error to forward. | ||
| * @returns {void} | ||
| */ | ||
| err => { | ||
| decoder.emit('error', err); | ||
| } | ||
| ); | ||
| flowDecoder.pipe(decoder); | ||
@@ -145,2 +159,7 @@ } | ||
| decoder, | ||
| /** | ||
| * Marks the selected node stream as consumed so the passthrough can continue. | ||
| * | ||
| * @returns {void} | ||
| */ | ||
| done: () => { | ||
@@ -147,0 +166,0 @@ if (typeof this.continue === 'function') { |
+180
-0
| import type { PassThrough, Transform } from 'node:stream'; | ||
| import type Headers = require('./headers'); | ||
| /** Value that is either present as `T` or explicitly unavailable as `false`. */ | ||
| export type Maybe<T> = T | false; | ||
| /** Single item in an IMAP-style MIME part number. */ | ||
| export type PartNumberItem = number | 'TEXT'; | ||
| /** IMAP-style path to a MIME part, for example `[1, 2, 'TEXT']`. */ | ||
| export type PartNumber = PartNumberItem[]; | ||
| /** Options passed through to libmime instances created by this package. */ | ||
| export interface LibmimeOptions { | ||
| /** Optional iconv-compatible implementation used by libmime for charset conversion. */ | ||
| Iconv?: unknown; | ||
| } | ||
| /** Configuration for `MessageSplitter` and MIME node parsing. */ | ||
| export interface SplitterOptions extends LibmimeOptions { | ||
| /** Treat `message/rfc822` parts as leaf nodes instead of parsing embedded messages. */ | ||
| ignoreEmbedded?: boolean; | ||
| /** Parse embedded messages as inline unless their disposition is `attachment`. */ | ||
| defaultInlineEmbedded?: boolean; | ||
| /** Maximum header block size, in bytes, allowed for a single MIME node. */ | ||
| maxHeadSize?: number; | ||
| /** Maximum number of MIME child nodes accepted before parsing fails. */ | ||
| maxChildNodes?: number; | ||
| } | ||
| /** Configuration for `ChunkedPassthrough`. */ | ||
| export interface ChunkedPassthroughOptions { | ||
| /** Buffered byte threshold for non-final chunks. Defaults to 64 KiB. */ | ||
| chunkSize?: number; | ||
| } | ||
| /** Configuration for `FlowedDecoder`. */ | ||
| export interface FlowedDecoderOptions extends LibmimeOptions { | ||
| /** Whether format=flowed uses RFC 3676 `DelSp=yes` space deletion semantics. */ | ||
| delSp?: boolean; | ||
| /** Source Content-Transfer-Encoding hint used during format=flowed handling. */ | ||
| encoding?: string | false; | ||
| } | ||
| /** Parsed raw header line with a normalized lookup key. */ | ||
| export interface HeaderLine { | ||
| /** Lower-case header key used for comparisons and lookups. */ | ||
| key: string; | ||
| /** Full header line, including the original field name, value, and any folded continuations. */ | ||
| line: string; | ||
| } | ||
| /** Decoded structured header value returned by libmime. */ | ||
| export interface DecodedHeader { | ||
| /** Header key returned by libmime for the decoded value. */ | ||
| key: string; | ||
| /** Unicode decoded header value. */ | ||
| value: string; | ||
| } | ||
| /** MIME node emitted by `MessageSplitter` and accepted by `MessageJoiner`. */ | ||
| export interface MimeNode { | ||
| /** Discriminator identifying this chunk as a MIME node. */ | ||
| type: 'node'; | ||
| /** Whether this node is the root message node. */ | ||
| root: boolean; | ||
| /** Parent MIME node, or `false` for the root node. */ | ||
| parentNode: MimeNode | false; | ||
| /** Boundary used by this multipart node, or `false` when not multipart. */ | ||
| _boundary: Buffer | false; | ||
| /** Boundary inherited from the parent multipart node, or `false` when absent. */ | ||
| _parentBoundary: Buffer | false; | ||
| /** Length, in bytes, of the raw header block collected for this node. */ | ||
| _headerlen: number; | ||
| /** Multipart subtype such as `mixed` or `alternative`, or `false` for leaf nodes. */ | ||
| multipart: string | false; | ||
| /** Content-Transfer-Encoding value, normalized to lower case, or `false` when absent. */ | ||
| encoding: string | false; | ||
| /** Parsed and mutable header collection, available after headers are parsed. */ | ||
| headers: Headers | false; | ||
| /** MIME content type such as `text/plain`, or `false` when unavailable. */ | ||
| contentType: string | false; | ||
| /** Charset parameter from Content-Type, or `false` when absent. */ | ||
| charset: string | false; | ||
| /** Content-Disposition value such as `inline` or `attachment`, or `false` when absent. */ | ||
| disposition: string | false; | ||
| /** Decoded filename from Content-Disposition or Content-Type parameters, or `false` when absent. */ | ||
| filename: string | false; | ||
| /** Whether this node is `text/*` with `format=flowed`. */ | ||
| flowed: boolean; | ||
| /** Whether flowed text uses `delsp=yes`. */ | ||
| delSp: boolean; | ||
| /** Splitter configuration used when parsing this node. */ | ||
| config: SplitterOptions; | ||
| /** Resolved IMAP-style part number for this node, or `false` before resolution. */ | ||
| partNr: PartNumber | false; | ||
| /** Number of child part numbers allocated by this node. */ | ||
| childPartNumbers: number; | ||
| /** Whether this node's content type is `message/rfc822`. */ | ||
| rfc822: boolean; | ||
| /** Whether an embedded `message/rfc822` node was parsed as a nested message. */ | ||
| messageNode?: boolean; | ||
| /** | ||
| * Builds the next child part number for this node. | ||
| * | ||
| * @param provided Optional explicit part number item to append. | ||
| * @returns Resolved MIME part number. | ||
| */ | ||
| getPartNr(provided?: PartNumberItem): PartNumber; | ||
| /** | ||
| * Appends one raw header line to this node while parsing. | ||
| * | ||
| * @param line Raw header line bytes; falsy values are ignored. | ||
| * @returns Nothing. | ||
| */ | ||
| addHeaderChunk(line?: Buffer | false): void; | ||
| /** | ||
| * Parses collected header bytes and populates MIME metadata fields. | ||
| * | ||
| * @returns Nothing. | ||
| */ | ||
| parseHeaders(): void; | ||
| /** | ||
| * Builds this node's header block. | ||
| * | ||
| * @returns Header bytes ending with an empty header/body separator line. | ||
| */ | ||
| getHeaders(): Buffer; | ||
| /** | ||
| * Sets or updates the Content-Type header value. | ||
| * | ||
| * @param contentType MIME content type to set; falsy keeps the current type. | ||
| * @returns Nothing. | ||
| */ | ||
| setContentType(contentType?: string | false): void; | ||
| /** | ||
| * Sets, updates, or removes the Content-Type charset parameter. | ||
| * | ||
| * @param charset Charset to set; falsy removes it when possible. | ||
| * @returns Nothing. | ||
| */ | ||
| setCharset(charset?: string | false): void; | ||
| /** | ||
| * Sets, updates, or removes the filename parameter. | ||
| * | ||
| * @param filename Filename to set; falsy removes it when possible. | ||
| * @returns Nothing. | ||
| */ | ||
| setFilename(filename?: string | false): void; | ||
| /** | ||
| * Creates a decoder stream for this node's transfer encoding. | ||
| * | ||
| * @returns Transform stream that outputs decoded content bytes. | ||
| */ | ||
| getDecoder(): Transform | PassThrough; | ||
| /** | ||
| * Creates an encoder stream and updates the Content-Transfer-Encoding header when needed. | ||
| * | ||
| * @param encoding Target transfer encoding; defaults to the node's current encoding. | ||
| * @returns Transform stream that outputs encoded content bytes. | ||
| */ | ||
| getEncoder(encoding?: string | false): Transform | PassThrough; | ||
| } | ||
| /** Data or body bytes emitted by `MessageSplitter`. */ | ||
| export interface MessageChunk { | ||
| /** MIME node that owns or precedes this chunk. */ | ||
| node: MimeNode; | ||
| /** Chunk kind: multipart structure bytes (`data`) or leaf content bytes (`body`). */ | ||
| type: 'data' | 'body'; | ||
| /** Raw chunk bytes. */ | ||
| value: Buffer; | ||
| } | ||
| /** Sentinel input used internally to finish a pending rewriter or streamer node. */ | ||
| export interface EmptyChunk { | ||
| /** Discriminator for an empty control chunk. */ | ||
| type: 'none'; | ||
| } | ||
| /** Object emitted by `MessageSplitter`: either a MIME node or a data/body byte chunk. */ | ||
| export type SplitterChunk = MimeNode | MessageChunk; | ||
| /** Object accepted by rewriter and streamer transforms. */ | ||
| export type RewriterInput = SplitterChunk | EmptyChunk; | ||
| /** | ||
| * Predicate used to select MIME nodes. | ||
| * | ||
| * @param node MIME node being inspected. | ||
| * @returns `true` to process the node, otherwise `false`. | ||
| */ | ||
| export type FilterFunc = (node: MimeNode) => boolean; | ||
| /** Error object that may include a Node-style string error code. */ | ||
| export type ErrorWithCode = Error & { code?: string }; | ||
| /** | ||
| * Callback that resumes processing after a selected node stream has ended. | ||
| * | ||
| * @returns Nothing. | ||
| */ | ||
| export type ContinueCallback = () => void; | ||
| /** Content transform stream used for decoded or encoded node bodies. */ | ||
| export type ContentStream = Transform | PassThrough; | ||
| /** Decoder stream with an internal readable-state guard used by rewriter/streamer. */ | ||
| export type DecoderStream = ContentStream & { $reading?: boolean }; | ||
| /** Internal grouping state used while splitter coalesces adjacent chunks. */ | ||
| export interface SplitterGroup { | ||
| /** MIME node associated with the group, when one exists. */ | ||
| node?: MimeNode; | ||
| /** Group kind currently being accumulated. */ | ||
| type: 'none' | 'node' | 'data' | 'body'; | ||
| /** Buffered raw bytes for `data` or `body` groups. */ | ||
| value?: Buffer; | ||
| } | ||
| /** Payload emitted with `NodeRewriter`'s `node` event. */ | ||
| export interface RewriterNode { | ||
| /** Selected MIME node whose body can be rewritten. */ | ||
| node: MimeNode; | ||
| /** Stream that yields decoded original body bytes. */ | ||
| decoder: Transform; | ||
| /** Stream that accepts replacement decoded bytes and emits properly encoded body bytes. */ | ||
| encoder: Transform; | ||
| } | ||
| /** Payload emitted with `NodeStreamer`'s `node` event. */ | ||
| export interface StreamerNode { | ||
| /** Selected MIME node whose body is being streamed. */ | ||
| node: MimeNode; | ||
| /** Stream that yields decoded original body bytes. */ | ||
| decoder: Transform; | ||
| /** | ||
| * Signals that the consumer has finished reading the selected node. | ||
| * | ||
| * @returns Nothing. | ||
| */ | ||
| done: () => void; | ||
| } |
+1
-1
| { | ||
| "name": "@zone-eu/mailsplit", | ||
| "version": "5.4.10", | ||
| "version": "5.4.11", | ||
| "description": "Split email messages into an object stream", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
120715
30.43%2478
38.51%