@zone-eu/mailsplit 5.4.10 → 5.4.12

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/index.d.ts CHANGED
@@ -9,36 +9,89 @@ import Headers = require('./lib/headers');
9
9
  import MimeNode = require('./lib/mime-node');
10
10
 
11
11
  export {
12
+ /** Splits raw message bytes into MIME node and content chunks. */
12
13
  Splitter,
14
+
15
+ /** Joins MIME node and content chunks back into raw message bytes. */
13
16
  Joiner,
17
+
18
+ /** Rewrites body content for MIME nodes selected by a filter function. */
14
19
  Rewriter,
20
+
21
+ /** Streams decoded body content for MIME nodes selected by a filter function. */
15
22
  Streamer,
23
+
24
+ /** Buffers byte input and emits larger Buffer chunks. */
16
25
  ChunkedPassthrough,
26
+
27
+ /** Parses, mutates, and rebuilds message header blocks. */
17
28
  Headers,
29
+
30
+ /** Represents one parsed MIME node and its header/body metadata. */
18
31
  MimeNode
19
32
  };
20
33
 
21
34
  export type {
35
+ /** Value that is either present as `T` or explicitly unavailable as `false`. */
22
36
  Maybe,
37
+
38
+ /** Single item in an IMAP-style MIME part number. */
23
39
  PartNumberItem,
40
+
41
+ /** IMAP-style path to a MIME part. */
24
42
  PartNumber,
43
+
44
+ /** Options passed through to libmime instances. */
25
45
  LibmimeOptions,
46
+
47
+ /** Configuration for `Splitter` and MIME node parsing. */
26
48
  SplitterOptions,
49
+
50
+ /** Configuration for `ChunkedPassthrough`. */
27
51
  ChunkedPassthroughOptions,
52
+
53
+ /** Configuration for format=flowed decoding. */
28
54
  FlowedDecoderOptions,
55
+
56
+ /** Parsed raw header line with a normalized lookup key. */
29
57
  HeaderLine,
58
+
59
+ /** Decoded structured header value. */
30
60
  DecodedHeader,
31
- MimeNode,
61
+
62
+ /** Data or body bytes emitted by `Splitter`. */
32
63
  MessageChunk,
64
+
65
+ /** Sentinel input used internally by rewriter/streamer transforms. */
33
66
  EmptyChunk,
67
+
68
+ /** Object emitted by `Splitter`. */
34
69
  SplitterChunk,
70
+
71
+ /** Object accepted by rewriter and streamer transforms. */
35
72
  RewriterInput,
73
+
74
+ /** Predicate used to select MIME nodes. */
36
75
  FilterFunc,
76
+
77
+ /** Error object that may include a Node-style string code. */
37
78
  ErrorWithCode,
79
+
80
+ /** Callback that resumes processing after a selected node stream ends. */
38
81
  ContinueCallback,
82
+
83
+ /** Content transform stream used for decoded or encoded node bodies. */
39
84
  ContentStream,
85
+
86
+ /** Decoder stream with an internal readable-state guard. */
40
87
  DecoderStream,
88
+
89
+ /** Internal splitter grouping state. */
41
90
  SplitterGroup,
91
+
92
+ /** Payload emitted with `Rewriter`'s `node` event. */
42
93
  RewriterNode,
94
+
95
+ /** Payload emitted with `Streamer`'s `node` event. */
43
96
  StreamerNode
44
97
  } from './lib/types';
@@ -1,12 +1,58 @@
1
1
  import { Transform } from 'node:stream';
2
2
  import type { ChunkedPassthroughOptions } from './types';
3
3
 
4
+ /** Transform stream that buffers byte input and emits larger Buffer chunks. */
4
5
  declare class ChunkedPassthrough extends Transform {
6
+ /**
7
+ * Creates a chunking passthrough transform that accepts Buffer input and emits Buffer chunks.
8
+ *
9
+ * @param options Optional chunk size configuration.
10
+ */
5
11
  constructor(options?: ChunkedPassthroughOptions);
12
+
13
+ /**
14
+ * Registers a listener for buffered byte chunks.
15
+ *
16
+ * @param event Event name.
17
+ * @param listener Receives each buffered Buffer chunk.
18
+ * @returns This passthrough instance.
19
+ */
6
20
  on(event: 'data', listener: (data: Buffer) => void): this;
21
+
22
+ /**
23
+ * Registers a one-time listener for the next buffered byte chunk.
24
+ *
25
+ * @param event Event name.
26
+ * @param listener Receives the next buffered Buffer chunk.
27
+ * @returns This passthrough instance.
28
+ */
7
29
  once(event: 'data', listener: (data: Buffer) => void): this;
30
+
31
+ /**
32
+ * Adds a listener for buffered byte chunks.
33
+ *
34
+ * @param event Event name.
35
+ * @param listener Receives each buffered Buffer chunk.
36
+ * @returns This passthrough instance.
37
+ */
8
38
  addListener(event: 'data', listener: (data: Buffer) => void): this;
39
+
40
+ /**
41
+ * Prepends a listener for buffered byte chunks.
42
+ *
43
+ * @param event Event name.
44
+ * @param listener Receives each buffered Buffer chunk.
45
+ * @returns This passthrough instance.
46
+ */
9
47
  prependListener(event: 'data', listener: (data: Buffer) => void): this;
48
+
49
+ /**
50
+ * Emits a buffered byte chunk.
51
+ *
52
+ * @param event Event name.
53
+ * @param data Buffer chunk to emit.
54
+ * @returns `true` when the event had listeners.
55
+ */
10
56
  emit(event: 'data', data: Buffer): boolean;
11
57
  }
12
58
 
@@ -2,6 +2,9 @@
2
2
 
3
3
  const { Transform } = require('stream');
4
4
 
5
+ /**
6
+ * Transform stream that buffers byte input and emits larger Buffer chunks.
7
+ */
5
8
  class ChunkedPassthrough extends Transform {
6
9
  /**
7
10
  * @param {import('..').ChunkedPassthroughOptions} [options]
@@ -1,12 +1,58 @@
1
1
  import { Transform } from 'node:stream';
2
2
  import type { FlowedDecoderOptions } from './types';
3
3
 
4
+ /** Transform stream that decodes `text/plain; format=flowed` content. */
4
5
  declare class FlowedDecoder extends Transform {
6
+ /**
7
+ * Creates a flowed text decoder that accepts encoded text bytes and emits decoded Buffer chunks.
8
+ *
9
+ * @param config Optional flowed text and charset decoding settings.
10
+ */
5
11
  constructor(config?: FlowedDecoderOptions);
12
+
13
+ /**
14
+ * Registers a listener for decoded flowed text bytes.
15
+ *
16
+ * @param event Event name.
17
+ * @param listener Receives decoded Buffer chunks.
18
+ * @returns This decoder instance.
19
+ */
6
20
  on(event: 'data', listener: (data: Buffer) => void): this;
21
+
22
+ /**
23
+ * Registers a one-time listener for the next decoded flowed text chunk.
24
+ *
25
+ * @param event Event name.
26
+ * @param listener Receives the next decoded Buffer chunk.
27
+ * @returns This decoder instance.
28
+ */
7
29
  once(event: 'data', listener: (data: Buffer) => void): this;
30
+
31
+ /**
32
+ * Adds a listener for decoded flowed text bytes.
33
+ *
34
+ * @param event Event name.
35
+ * @param listener Receives decoded Buffer chunks.
36
+ * @returns This decoder instance.
37
+ */
8
38
  addListener(event: 'data', listener: (data: Buffer) => void): this;
39
+
40
+ /**
41
+ * Prepends a listener for decoded flowed text bytes.
42
+ *
43
+ * @param event Event name.
44
+ * @param listener Receives decoded Buffer chunks.
45
+ * @returns This decoder instance.
46
+ */
9
47
  prependListener(event: 'data', listener: (data: Buffer) => void): this;
48
+
49
+ /**
50
+ * Emits a decoded flowed text chunk.
51
+ *
52
+ * @param event Event name.
53
+ * @param data Buffer chunk to emit.
54
+ * @returns `true` when the event had listeners.
55
+ */
10
56
  emit(event: 'data', data: Buffer): boolean;
11
57
  }
12
58
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // Helper class to rewrite nodes with specific mime type
3
+ // Helper class to decode format=flowed text nodes
4
4
 
5
5
  const Transform = require('stream').Transform;
6
6
  const libmime = require('libmime');
@@ -10,14 +10,13 @@ const libmime = require('libmime');
10
10
  const Libmime = /** @type {any} */ (libmime.Libmime);
11
11
 
12
12
  /**
13
- * Really bad "stream" transform to parse format=flowed content
13
+ * Transform stream that decodes text/plain format=flowed content.
14
14
  *
15
- * @constructor
16
- * @param {FlowedDecoderOptions} [config]
15
+ * @param {FlowedDecoderOptions} [config] Flowed text and charset decoding settings.
17
16
  */
18
17
  class FlowedDecoder extends Transform {
19
18
  /**
20
- * @param {FlowedDecoderOptions} [config]
19
+ * @param {FlowedDecoderOptions} [config] Flowed text and charset decoding settings.
21
20
  */
22
21
  constructor(config) {
23
22
  super();
package/lib/headers.d.ts CHANGED
@@ -1,23 +1,116 @@
1
1
  import type { DecodedHeader, HeaderLine, LibmimeOptions } from './types';
2
2
 
3
+ /** Mutable parser and builder for RFC-style message header blocks. */
3
4
  declare class Headers {
5
+ /** Whether header lines have been modified after construction. */
4
6
  changed: boolean;
7
+
8
+ /** Original unparsed header source, or `false` when constructed from parsed lines. */
5
9
  headers: string | Buffer | false;
10
+
11
+ /** Whether `headers` has been parsed into `lines`. */
6
12
  parsed: boolean;
13
+
14
+ /** Parsed header lines, or `false` until parsing occurs. */
7
15
  lines: HeaderLine[] | false;
16
+
17
+ /** MBOX `From ` prefix line, or `false` when absent. */
8
18
  mbox: string | false;
19
+
20
+ /** HTTP request prefix line, or `false` when absent. */
9
21
  http: string | false;
10
22
 
23
+ /**
24
+ * Creates a mutable header collection.
25
+ *
26
+ * @param headers Raw header bytes/string, already parsed header lines, or `false` for an empty collection.
27
+ * @param config Optional libmime configuration.
28
+ */
11
29
  constructor(headers?: string | Buffer | HeaderLine[] | false, config?: LibmimeOptions);
30
+
31
+ /**
32
+ * Checks whether at least one header with the requested key exists.
33
+ *
34
+ * @param key Header field name to find, case-insensitively.
35
+ * @returns `true` when the header exists.
36
+ */
12
37
  hasHeader(key: string): boolean;
38
+
39
+ /**
40
+ * Gets all raw header lines for a key.
41
+ *
42
+ * @param key Header field name to find, case-insensitively.
43
+ * @returns Full decoded header lines, including field names.
44
+ */
13
45
  get(key: string): string[];
46
+
47
+ /**
48
+ * Gets all decoded structured header values for a key.
49
+ *
50
+ * @param key Header field name to decode, case-insensitively.
51
+ * @returns Decoded header entries with key and value fields.
52
+ */
14
53
  getDecoded(key: string): DecodedHeader[];
54
+
55
+ /**
56
+ * Gets the first decoded header value for a key.
57
+ *
58
+ * @param key Header field name to find, case-insensitively.
59
+ * @returns Trimmed decoded value, or an empty string when the header is absent.
60
+ */
15
61
  getFirst(key: string): string;
62
+
63
+ /**
64
+ * Gets the mutable parsed header list.
65
+ *
66
+ * @returns Parsed header lines in message order.
67
+ */
16
68
  getList(): HeaderLine[];
69
+
70
+ /**
71
+ * Adds a folded header line.
72
+ *
73
+ * @param key Header field name to add.
74
+ * @param value Header value; `undefined` leaves the collection unchanged.
75
+ * @param index Insertion index, where omitted or less than 1 inserts at the top.
76
+ * @returns Nothing.
77
+ */
17
78
  add(key: string, value?: string | number | Buffer, index?: number): void;
79
+
80
+ /**
81
+ * Adds a preformatted header line.
82
+ *
83
+ * @param key Header field name used for normalized lookup.
84
+ * @param line Full header line to insert; falsy values leave the collection unchanged.
85
+ * @param index Insertion index, where omitted or less than 1 inserts at the top.
86
+ * @returns Nothing.
87
+ */
18
88
  addFormatted(key: string, line?: string | Buffer | false, index?: number): void;
89
+
90
+ /**
91
+ * Removes all headers matching a key.
92
+ *
93
+ * @param key Header field name to remove, case-insensitively.
94
+ * @returns Nothing.
95
+ */
19
96
  remove(key: string): void;
97
+
98
+ /**
99
+ * Replaces matching headers with a new folded header value.
100
+ *
101
+ * @param key Header field name to update.
102
+ * @param value Header value to write; `undefined` removes matching values without adding a replacement.
103
+ * @param relativeIndex Optional zero-based index among headers with the same key.
104
+ * @returns Nothing.
105
+ */
20
106
  update(key: string, value?: string | number | Buffer, relativeIndex?: number): void;
107
+
108
+ /**
109
+ * Builds a raw header block.
110
+ *
111
+ * @param lineEnd Line ending to use when rebuilding changed headers; defaults to CRLF.
112
+ * @returns Header bytes ending with an empty header/body separator line.
113
+ */
21
114
  build(lineEnd?: string | false): Buffer;
22
115
  }
23
116
 
package/lib/headers.js CHANGED
@@ -9,13 +9,13 @@ const libmime = require('libmime');
9
9
  const Libmime = /** @type {any} */ (libmime.Libmime);
10
10
 
11
11
  /**
12
- * Class Headers to parse and handle message headers. Headers instance allows to
13
- * check existing, delete or add new headers
12
+ * Parses and builds message headers. A Headers instance allows callers to
13
+ * inspect, delete, update, and add header lines.
14
14
  */
15
15
  class Headers {
16
16
  /**
17
- * @param {string | Buffer | HeaderLine[] | false} [headers]
18
- * @param {LibmimeOptions} [config]
17
+ * @param {string | Buffer | HeaderLine[] | false} [headers] Raw header source or already parsed lines.
18
+ * @param {LibmimeOptions} [config] Optional libmime configuration.
19
19
  */
20
20
  constructor(headers, config) {
21
21
  config = config || {};
@@ -1,11 +1,55 @@
1
1
  import { Transform } from 'node:stream';
2
2
 
3
+ /** Transform stream that joins splitter objects back into raw email bytes. */
3
4
  declare class MessageJoiner extends Transform {
5
+ /**
6
+ * Creates a joiner that accepts splitter objects and emits Buffer chunks.
7
+ */
4
8
  constructor();
9
+
10
+ /**
11
+ * Registers a listener for generated message bytes.
12
+ *
13
+ * @param event Event name.
14
+ * @param listener Receives each generated Buffer chunk.
15
+ * @returns This joiner instance.
16
+ */
5
17
  on(event: 'data', listener: (data: Buffer) => void): this;
18
+
19
+ /**
20
+ * Registers a one-time listener for generated message bytes.
21
+ *
22
+ * @param event Event name.
23
+ * @param listener Receives the next generated Buffer chunk.
24
+ * @returns This joiner instance.
25
+ */
6
26
  once(event: 'data', listener: (data: Buffer) => void): this;
27
+
28
+ /**
29
+ * Adds a listener for generated message bytes.
30
+ *
31
+ * @param event Event name.
32
+ * @param listener Receives each generated Buffer chunk.
33
+ * @returns This joiner instance.
34
+ */
7
35
  addListener(event: 'data', listener: (data: Buffer) => void): this;
36
+
37
+ /**
38
+ * Prepends a listener for generated message bytes.
39
+ *
40
+ * @param event Event name.
41
+ * @param listener Receives each generated Buffer chunk.
42
+ * @returns This joiner instance.
43
+ */
8
44
  prependListener(event: 'data', listener: (data: Buffer) => void): this;
45
+
46
+ /**
47
+ * Emits a generated message byte chunk.
48
+ *
49
+ * @param event Event name.
50
+ * @param data Buffer chunk to emit.
51
+ * @returns `true` when the event had listeners.
52
+ */
9
53
  emit(event: 'data', data: Buffer): boolean;
10
54
  }
11
55
 
@@ -4,7 +4,13 @@ const Transform = require('stream').Transform;
4
4
 
5
5
  /** @typedef {import('..').SplitterChunk} SplitterChunk */
6
6
 
7
+ /**
8
+ * Transform stream that joins splitter objects back into raw message bytes.
9
+ */
7
10
  class MessageJoiner extends Transform {
11
+ /**
12
+ * Creates a joiner that accepts splitter objects and emits Buffer chunks.
13
+ */
8
14
  constructor() {
9
15
  let options = {
10
16
  readableObjectMode: false,
@@ -1,12 +1,58 @@
1
1
  import { Transform } from 'node:stream';
2
2
  import type { SplitterChunk, SplitterOptions } from './types';
3
3
 
4
+ /** Transform stream that splits raw email bytes into MIME node and content chunks. */
4
5
  declare class MessageSplitter extends Transform {
6
+ /**
7
+ * Creates a splitter that accepts Buffer input and emits `SplitterChunk` objects.
8
+ *
9
+ * @param config Optional parser limits and embedded-message behavior.
10
+ */
5
11
  constructor(config?: SplitterOptions);
12
+
13
+ /**
14
+ * Registers a listener for parsed splitter chunks.
15
+ *
16
+ * @param event Event name.
17
+ * @param listener Receives each parsed MIME node, data chunk, or body chunk.
18
+ * @returns This splitter instance.
19
+ */
6
20
  on(event: 'data', listener: (data: SplitterChunk) => void): this;
21
+
22
+ /**
23
+ * Registers a one-time listener for the next parsed splitter chunk.
24
+ *
25
+ * @param event Event name.
26
+ * @param listener Receives the next parsed MIME node, data chunk, or body chunk.
27
+ * @returns This splitter instance.
28
+ */
7
29
  once(event: 'data', listener: (data: SplitterChunk) => void): this;
30
+
31
+ /**
32
+ * Adds a listener for parsed splitter chunks.
33
+ *
34
+ * @param event Event name.
35
+ * @param listener Receives each parsed MIME node, data chunk, or body chunk.
36
+ * @returns This splitter instance.
37
+ */
8
38
  addListener(event: 'data', listener: (data: SplitterChunk) => void): this;
39
+
40
+ /**
41
+ * Prepends a listener for parsed splitter chunks.
42
+ *
43
+ * @param event Event name.
44
+ * @param listener Receives each parsed MIME node, data chunk, or body chunk.
45
+ * @returns This splitter instance.
46
+ */
9
47
  prependListener(event: 'data', listener: (data: SplitterChunk) => void): this;
48
+
49
+ /**
50
+ * Emits a parsed splitter chunk.
51
+ *
52
+ * @param event Event name.
53
+ * @param data MIME node, data chunk, or body chunk to emit.
54
+ * @returns `true` when the event had listeners.
55
+ */
10
56
  emit(event: 'data', data: SplitterChunk): boolean;
11
57
  }
12
58
 
@@ -16,6 +16,9 @@ const MAX_CHILD_NODES = 1000;
16
16
  const HEAD = 0x01;
17
17
  const BODY = 0x02;
18
18
 
19
+ /**
20
+ * Transform stream that splits raw email bytes into MIME node and content chunks.
21
+ */
19
22
  class MessageSplitter extends Transform {
20
23
  /**
21
24
  * @param {SplitterOptions} [config]
@@ -59,7 +62,12 @@ class MessageSplitter extends Transform {
59
62
  let groupstart = this.line ? -this.line.length : 0;
60
63
  let groupend = 0;
61
64
 
62
- /** @param {MessageChunk} data */
65
+ /**
66
+ * Removes a pending line break from body data that belongs to a following boundary.
67
+ *
68
+ * @param {MessageChunk} data Body chunk to adjust in place.
69
+ * @returns {void}
70
+ */
63
71
  let checkTrailingLinebreak = data => {
64
72
  if (data.type === 'body' && data.node.parentNode && data.value && data.value.length) {
65
73
  if (data.value[data.value.length - 1] === 0x0a) {
@@ -88,6 +96,11 @@ class MessageSplitter extends Transform {
88
96
  }
89
97
  };
90
98
 
99
+ /**
100
+ * Iterates the current input chunk line by line and emits parsed groups.
101
+ *
102
+ * @returns {void}
103
+ */
91
104
  let iterateData = () => {
92
105
  for (let len = chunk.length; i < len; i++) {
93
106
  // find next <LF>
@@ -1,37 +1,143 @@
1
1
  import type { ContentStream, MimeNode as MimeNodeShape, PartNumber, PartNumberItem, SplitterOptions } from './types';
2
2
  import type Headers = require('./headers');
3
3
 
4
+ /** Parsed MIME node with mutable headers and content encoding helpers. */
4
5
  declare class MimeNode implements MimeNodeShape {
6
+ /** Discriminator identifying this chunk as a MIME node. */
5
7
  type: 'node';
8
+
9
+ /** Whether this node is the root message node. */
6
10
  root: boolean;
11
+
12
+ /** Parent MIME node, or `false` for the root node. */
7
13
  parentNode: MimeNodeShape | false;
14
+
15
+ /** Boundary used by this multipart node, or `false` when not multipart. */
8
16
  _boundary: Buffer | false;
17
+
18
+ /** Boundary inherited from the parent multipart node, or `false` when absent. */
9
19
  _parentBoundary: Buffer | false;
20
+
21
+ /** Length, in bytes, of the raw header block collected for this node. */
10
22
  _headerlen: number;
23
+
24
+ /** Multipart subtype such as `mixed` or `alternative`, or `false` for leaf nodes. */
11
25
  multipart: string | false;
26
+
27
+ /** Content-Transfer-Encoding value, normalized to lower case, or `false` when absent. */
12
28
  encoding: string | false;
29
+
30
+ /** Parsed and mutable header collection, available after headers are parsed. */
13
31
  headers: Headers | false;
32
+
33
+ /** MIME content type such as `text/plain`, or `false` when unavailable. */
14
34
  contentType: string | false;
35
+
36
+ /** Charset parameter from Content-Type, or `false` when absent. */
15
37
  charset: string | false;
38
+
39
+ /** Content-Disposition value such as `inline` or `attachment`, or `false` when absent. */
16
40
  disposition: string | false;
41
+
42
+ /** Decoded filename from Content-Disposition or Content-Type parameters, or `false` when absent. */
17
43
  filename: string | false;
44
+
45
+ /** Whether this node is `text/*` with `format=flowed`. */
18
46
  flowed: boolean;
47
+
48
+ /** Whether flowed text uses `delsp=yes`. */
19
49
  delSp: boolean;
50
+
51
+ /** Splitter configuration used when parsing this node. */
20
52
  config: SplitterOptions;
53
+
54
+ /** Resolved IMAP-style part number for this node, or `false` before resolution. */
21
55
  partNr: PartNumber | false;
56
+
57
+ /** Number of child part numbers allocated by this node. */
22
58
  childPartNumbers: number;
59
+
60
+ /** Whether this node's content type is `message/rfc822`. */
23
61
  rfc822: boolean;
62
+
63
+ /** Whether an embedded `message/rfc822` node was parsed as a nested message. */
24
64
  messageNode?: boolean;
25
65
 
66
+ /**
67
+ * Creates a MIME node with empty header state.
68
+ *
69
+ * @param parentNode Parent node, or `false`/omitted for the root node.
70
+ * @param config Optional splitter and libmime configuration.
71
+ */
26
72
  constructor(parentNode?: MimeNodeShape | false, config?: SplitterOptions);
73
+
74
+ /**
75
+ * Builds the next child part number for this node.
76
+ *
77
+ * @param provided Optional explicit part number item to append.
78
+ * @returns Resolved MIME part number.
79
+ */
27
80
  getPartNr(provided?: PartNumberItem): PartNumber;
81
+
82
+ /**
83
+ * Appends one raw header line to this node while parsing.
84
+ *
85
+ * @param line Raw header line bytes; falsy values are ignored.
86
+ * @returns Nothing.
87
+ */
28
88
  addHeaderChunk(line?: Buffer | false): void;
89
+
90
+ /**
91
+ * Parses collected header bytes and populates MIME metadata fields.
92
+ *
93
+ * @returns Nothing.
94
+ */
29
95
  parseHeaders(): void;
96
+
97
+ /**
98
+ * Builds this node's header block.
99
+ *
100
+ * @returns Header bytes ending with an empty header/body separator line.
101
+ */
30
102
  getHeaders(): Buffer;
103
+
104
+ /**
105
+ * Sets or updates the Content-Type header value.
106
+ *
107
+ * @param contentType MIME content type to set; falsy keeps the current type.
108
+ * @returns Nothing.
109
+ */
31
110
  setContentType(contentType?: string | false): void;
111
+
112
+ /**
113
+ * Sets, updates, or removes the Content-Type charset parameter.
114
+ *
115
+ * @param charset Charset to set; falsy removes it when possible.
116
+ * @returns Nothing.
117
+ */
32
118
  setCharset(charset?: string | false): void;
119
+
120
+ /**
121
+ * Sets, updates, or removes the filename parameter.
122
+ *
123
+ * @param filename Filename to set; falsy removes it when possible.
124
+ * @returns Nothing.
125
+ */
33
126
  setFilename(filename?: string | false): void;
127
+
128
+ /**
129
+ * Creates a decoder stream for this node's transfer encoding.
130
+ *
131
+ * @returns Transform stream that outputs decoded content bytes.
132
+ */
34
133
  getDecoder(): ContentStream;
134
+
135
+ /**
136
+ * Creates an encoder stream and updates the Content-Transfer-Encoding header when needed.
137
+ *
138
+ * @param encoding Target transfer encoding; defaults to the node's current encoding.
139
+ * @returns Transform stream that outputs encoded content bytes.
140
+ */
35
141
  getEncoder(encoding?: string | false): ContentStream;
36
142
  }
37
143
 
package/lib/mime-node.js CHANGED
@@ -18,10 +18,13 @@ const pathlib = require('path');
18
18
 
19
19
  const Libmime = /** @type {any} */ (libmime.Libmime);
20
20
 
21
+ /**
22
+ * Parsed MIME node with mutable headers and transfer-encoding helpers.
23
+ */
21
24
  class MimeNode {
22
25
  /**
23
- * @param {MimeNodeType | false} parentNode
24
- * @param {SplitterOptions} [config]
26
+ * @param {MimeNodeType | false} parentNode Parent node, or false for the root node.
27
+ * @param {SplitterOptions} [config] Splitter and libmime configuration.
25
28
  */
26
29
  constructor(parentNode, config) {
27
30
  /** @type {'node'} */
@@ -1,17 +1,104 @@
1
1
  import { Transform } from 'node:stream';
2
2
  import type { FilterFunc, RewriterNode, SplitterChunk } from './types';
3
3
 
4
+ /** Transform stream that replaces the body content of selected MIME nodes. */
4
5
  declare class NodeRewriter extends Transform {
6
+ /**
7
+ * Creates a node rewriter that accepts splitter chunks and emits rewritten splitter chunks.
8
+ *
9
+ * @param filterFunc Predicate that selects MIME nodes to rewrite.
10
+ * @param rewriteAction Optional compatibility hook stored on the instance; consumers usually handle the `node` event.
11
+ */
5
12
  constructor(filterFunc: FilterFunc, rewriteAction?: Function);
13
+
14
+ /**
15
+ * Registers a listener for rewritten splitter chunks.
16
+ *
17
+ * @param event Event name.
18
+ * @param listener Receives each outgoing MIME node, data chunk, or body chunk.
19
+ * @returns This rewriter instance.
20
+ */
6
21
  on(event: 'data', listener: (data: SplitterChunk) => void): this;
22
+
23
+ /**
24
+ * Registers a listener for selected nodes.
25
+ *
26
+ * @param event Event name.
27
+ * @param listener Receives decoder and encoder streams for a selected node.
28
+ * @returns This rewriter instance.
29
+ */
7
30
  on(event: 'node', listener: (data: RewriterNode) => void): this;
31
+
32
+ /**
33
+ * Registers a one-time listener for the next rewritten splitter chunk.
34
+ *
35
+ * @param event Event name.
36
+ * @param listener Receives the next outgoing MIME node, data chunk, or body chunk.
37
+ * @returns This rewriter instance.
38
+ */
8
39
  once(event: 'data', listener: (data: SplitterChunk) => void): this;
40
+
41
+ /**
42
+ * Registers a one-time listener for the next selected node.
43
+ *
44
+ * @param event Event name.
45
+ * @param listener Receives decoder and encoder streams for the next selected node.
46
+ * @returns This rewriter instance.
47
+ */
9
48
  once(event: 'node', listener: (data: RewriterNode) => void): this;
49
+
50
+ /**
51
+ * Adds a listener for rewritten splitter chunks.
52
+ *
53
+ * @param event Event name.
54
+ * @param listener Receives each outgoing MIME node, data chunk, or body chunk.
55
+ * @returns This rewriter instance.
56
+ */
10
57
  addListener(event: 'data', listener: (data: SplitterChunk) => void): this;
58
+
59
+ /**
60
+ * Adds a listener for selected nodes.
61
+ *
62
+ * @param event Event name.
63
+ * @param listener Receives decoder and encoder streams for a selected node.
64
+ * @returns This rewriter instance.
65
+ */
11
66
  addListener(event: 'node', listener: (data: RewriterNode) => void): this;
67
+
68
+ /**
69
+ * Prepends a listener for rewritten splitter chunks.
70
+ *
71
+ * @param event Event name.
72
+ * @param listener Receives each outgoing MIME node, data chunk, or body chunk.
73
+ * @returns This rewriter instance.
74
+ */
12
75
  prependListener(event: 'data', listener: (data: SplitterChunk) => void): this;
76
+
77
+ /**
78
+ * Prepends a listener for selected nodes.
79
+ *
80
+ * @param event Event name.
81
+ * @param listener Receives decoder and encoder streams for a selected node.
82
+ * @returns This rewriter instance.
83
+ */
13
84
  prependListener(event: 'node', listener: (data: RewriterNode) => void): this;
85
+
86
+ /**
87
+ * Emits a rewritten splitter chunk.
88
+ *
89
+ * @param event Event name.
90
+ * @param data MIME node, data chunk, or body chunk to emit.
91
+ * @returns `true` when the event had listeners.
92
+ */
14
93
  emit(event: 'data', data: SplitterChunk): boolean;
94
+
95
+ /**
96
+ * Emits a selected-node payload.
97
+ *
98
+ * @param event Event name.
99
+ * @param data Selected node payload containing decoder and encoder streams.
100
+ * @returns `true` when the event had listeners.
101
+ */
15
102
  emit(event: 'node', data: RewriterNode): boolean;
16
103
  }
17
104
 
@@ -14,16 +14,16 @@ const FlowedDecoder = require('./flowed-decoder');
14
14
  /** @typedef {import('..').ContinueCallback} ContinueCallback */
15
15
 
16
16
  /**
17
- * NodeRewriter Transform stream. Updates content for all nodes with specified mime type
17
+ * NodeRewriter Transform stream. Updates content for all nodes selected by the
18
+ * filter function.
18
19
  *
19
- * @constructor
20
- * @param {FilterFunc} filterFunc Function to select nodes to rewrite
21
- * @param {Function} [rewriteAction] Function to run with the node content
20
+ * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to rewrite it.
21
+ * @param {Function} [rewriteAction] Optional compatibility hook stored on the instance.
22
22
  */
23
23
  class NodeRewriter extends Transform {
24
24
  /**
25
- * @param {FilterFunc} filterFunc
26
- * @param {Function} [rewriteAction]
25
+ * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to rewrite it.
26
+ * @param {Function} [rewriteAction] Optional compatibility hook stored on the instance.
27
27
  */
28
28
  constructor(filterFunc, rewriteAction) {
29
29
  let options = {
@@ -128,6 +128,11 @@ class NodeRewriter extends Transform {
128
128
  let firstChunk = true;
129
129
  decoder.$reading = false;
130
130
 
131
+ /**
132
+ * Reads encoded replacement bytes and forwards them as body chunks.
133
+ *
134
+ * @returns {void | NodeJS.Immediate}
135
+ */
131
136
  let readFromEncoder = () => {
132
137
  decoder.$reading = true;
133
138
 
@@ -202,9 +207,18 @@ class NodeRewriter extends Transform {
202
207
  delSp: node.delSp,
203
208
  encoding: node.encoding || false
204
209
  });
205
- flowDecoder.on('error', /** @param {Error} err */ err => {
206
- decoder.emit('error', err);
207
- });
210
+ flowDecoder.on(
211
+ 'error',
212
+ /**
213
+ * Forwards flowed decoder errors to the replacement decoder.
214
+ *
215
+ * @param {Error} err Decoder error to forward.
216
+ * @returns {void}
217
+ */
218
+ err => {
219
+ decoder.emit('error', err);
220
+ }
221
+ );
208
222
  flowDecoder.pipe(decoder);
209
223
 
210
224
  // we don't know what kind of data we are going to get, does it comply with the
@@ -1,17 +1,104 @@
1
1
  import { Transform } from 'node:stream';
2
2
  import type { FilterFunc, SplitterChunk, StreamerNode } from './types';
3
3
 
4
+ /** Transform stream that exposes decoded body streams for selected MIME nodes without replacing them. */
4
5
  declare class NodeStreamer extends Transform {
6
+ /**
7
+ * Creates a node streamer that accepts splitter chunks and passes them through unchanged.
8
+ *
9
+ * @param filterFunc Predicate that selects MIME nodes to stream.
10
+ * @param streamAction Optional compatibility hook stored on the instance; consumers usually handle the `node` event.
11
+ */
5
12
  constructor(filterFunc: FilterFunc, streamAction?: Function);
13
+
14
+ /**
15
+ * Registers a listener for passed-through splitter chunks.
16
+ *
17
+ * @param event Event name.
18
+ * @param listener Receives each outgoing MIME node, data chunk, or body chunk.
19
+ * @returns This streamer instance.
20
+ */
6
21
  on(event: 'data', listener: (data: SplitterChunk) => void): this;
22
+
23
+ /**
24
+ * Registers a listener for selected nodes.
25
+ *
26
+ * @param event Event name.
27
+ * @param listener Receives a decoder stream and completion callback for a selected node.
28
+ * @returns This streamer instance.
29
+ */
7
30
  on(event: 'node', listener: (data: StreamerNode) => void): this;
31
+
32
+ /**
33
+ * Registers a one-time listener for the next passed-through splitter chunk.
34
+ *
35
+ * @param event Event name.
36
+ * @param listener Receives the next outgoing MIME node, data chunk, or body chunk.
37
+ * @returns This streamer instance.
38
+ */
8
39
  once(event: 'data', listener: (data: SplitterChunk) => void): this;
40
+
41
+ /**
42
+ * Registers a one-time listener for the next selected node.
43
+ *
44
+ * @param event Event name.
45
+ * @param listener Receives a decoder stream and completion callback for the next selected node.
46
+ * @returns This streamer instance.
47
+ */
9
48
  once(event: 'node', listener: (data: StreamerNode) => void): this;
49
+
50
+ /**
51
+ * Adds a listener for passed-through splitter chunks.
52
+ *
53
+ * @param event Event name.
54
+ * @param listener Receives each outgoing MIME node, data chunk, or body chunk.
55
+ * @returns This streamer instance.
56
+ */
10
57
  addListener(event: 'data', listener: (data: SplitterChunk) => void): this;
58
+
59
+ /**
60
+ * Adds a listener for selected nodes.
61
+ *
62
+ * @param event Event name.
63
+ * @param listener Receives a decoder stream and completion callback for a selected node.
64
+ * @returns This streamer instance.
65
+ */
11
66
  addListener(event: 'node', listener: (data: StreamerNode) => void): this;
67
+
68
+ /**
69
+ * Prepends a listener for passed-through splitter chunks.
70
+ *
71
+ * @param event Event name.
72
+ * @param listener Receives each outgoing MIME node, data chunk, or body chunk.
73
+ * @returns This streamer instance.
74
+ */
12
75
  prependListener(event: 'data', listener: (data: SplitterChunk) => void): this;
76
+
77
+ /**
78
+ * Prepends a listener for selected nodes.
79
+ *
80
+ * @param event Event name.
81
+ * @param listener Receives a decoder stream and completion callback for a selected node.
82
+ * @returns This streamer instance.
83
+ */
13
84
  prependListener(event: 'node', listener: (data: StreamerNode) => void): this;
85
+
86
+ /**
87
+ * Emits a passed-through splitter chunk.
88
+ *
89
+ * @param event Event name.
90
+ * @param data MIME node, data chunk, or body chunk to emit.
91
+ * @returns `true` when the event had listeners.
92
+ */
14
93
  emit(event: 'data', data: SplitterChunk): boolean;
94
+
95
+ /**
96
+ * Emits a selected-node payload.
97
+ *
98
+ * @param event Event name.
99
+ * @param data Selected node payload containing decoder stream and completion callback.
100
+ * @returns `true` when the event had listeners.
101
+ */
15
102
  emit(event: 'node', data: StreamerNode): boolean;
16
103
  }
17
104
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // Helper class to rewrite nodes with specific mime type
3
+ // Helper class to stream selected nodes by MIME metadata
4
4
 
5
5
  const Transform = require('stream').Transform;
6
6
  const FlowedDecoder = require('./flowed-decoder');
@@ -13,16 +13,16 @@ const FlowedDecoder = require('./flowed-decoder');
13
13
  /** @typedef {import('..').ContinueCallback} ContinueCallback */
14
14
 
15
15
  /**
16
- * NodeRewriter Transform stream. Updates content for all nodes with specified mime type
16
+ * NodeStreamer Transform stream. Exposes decoded content for nodes selected by
17
+ * the filter function while passing the original message through unchanged.
17
18
  *
18
- * @constructor
19
- * @param {FilterFunc} filterFunc Function to select nodes to stream
20
- * @param {Function} [streamAction] Function to run with the node content
19
+ * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to stream it.
20
+ * @param {Function} [streamAction] Optional compatibility hook stored on the instance.
21
21
  */
22
22
  class NodeStreamer extends Transform {
23
23
  /**
24
- * @param {FilterFunc} filterFunc
25
- * @param {Function} [streamAction]
24
+ * @param {FilterFunc} filterFunc Function that receives a MIME node and returns true to stream it.
25
+ * @param {Function} [streamAction] Optional compatibility hook stored on the instance.
26
26
  */
27
27
  constructor(filterFunc, streamAction) {
28
28
  let options = {
@@ -89,6 +89,11 @@ class NodeStreamer extends Transform {
89
89
  // the parsed data is completely processed, so we store a reference to the
90
90
  // continue callback
91
91
 
92
+ /**
93
+ * Resumes processing with the first chunk after the streamed node.
94
+ *
95
+ * @returns {void}
96
+ */
92
97
  let doContinue = () => {
93
98
  this.continue = false;
94
99
  this.decoder = false;
@@ -130,15 +135,29 @@ class NodeStreamer extends Transform {
130
135
  decoder = new FlowedDecoder({
131
136
  delSp: node.delSp
132
137
  });
133
- flowDecoder.on('error', /** @param {Error} err */ err => {
134
- decoder.emit('error', err);
135
- });
138
+ flowDecoder.on(
139
+ 'error',
140
+ /**
141
+ * Forwards flowed decoder errors to the output decoder.
142
+ *
143
+ * @param {Error} err Decoder error to forward.
144
+ * @returns {void}
145
+ */
146
+ err => {
147
+ decoder.emit('error', err);
148
+ }
149
+ );
136
150
  flowDecoder.pipe(decoder);
137
151
  }
138
152
 
139
153
  return {
140
154
  node,
141
155
  decoder,
156
+ /**
157
+ * Marks the selected node stream as consumed so the passthrough can continue.
158
+ *
159
+ * @returns {void}
160
+ */
142
161
  done: () => {
143
162
  if (typeof this.continue === 'function') {
144
163
  // called once input stream is processed
package/lib/types.d.ts CHANGED
@@ -1,105 +1,285 @@
1
1
  import type { PassThrough, Transform } from 'node:stream';
2
2
  import type Headers = require('./headers');
3
3
 
4
+ /** Value that is either present as `T` or explicitly unavailable as `false`. */
4
5
  export type Maybe<T> = T | false;
6
+
7
+ /** Single item in an IMAP-style MIME part number. */
5
8
  export type PartNumberItem = number | 'TEXT';
9
+
10
+ /** IMAP-style path to a MIME part, for example `[1, 2, 'TEXT']`. */
6
11
  export type PartNumber = PartNumberItem[];
7
12
 
13
+ /** Options passed through to libmime instances created by this package. */
8
14
  export interface LibmimeOptions {
15
+ /** Optional iconv-compatible implementation used by libmime for charset conversion. */
9
16
  Iconv?: unknown;
10
17
  }
11
18
 
19
+ /** Configuration for `MessageSplitter` and MIME node parsing. */
12
20
  export interface SplitterOptions extends LibmimeOptions {
21
+ /** Treat `message/rfc822` parts as leaf nodes instead of parsing embedded messages. */
13
22
  ignoreEmbedded?: boolean;
23
+
24
+ /** Parse embedded messages as inline unless their disposition is `attachment`. */
14
25
  defaultInlineEmbedded?: boolean;
26
+
27
+ /** Maximum header block size, in bytes, allowed for a single MIME node. */
15
28
  maxHeadSize?: number;
29
+
30
+ /** Maximum number of MIME child nodes accepted before parsing fails. */
16
31
  maxChildNodes?: number;
17
32
  }
18
33
 
34
+ /** Configuration for `ChunkedPassthrough`. */
19
35
  export interface ChunkedPassthroughOptions {
36
+ /** Buffered byte threshold for non-final chunks. Defaults to 64 KiB. */
20
37
  chunkSize?: number;
21
38
  }
22
39
 
40
+ /** Configuration for `FlowedDecoder`. */
23
41
  export interface FlowedDecoderOptions extends LibmimeOptions {
42
+ /** Whether format=flowed uses RFC 3676 `DelSp=yes` space deletion semantics. */
24
43
  delSp?: boolean;
44
+
45
+ /** Source Content-Transfer-Encoding hint used during format=flowed handling. */
25
46
  encoding?: string | false;
26
47
  }
27
48
 
49
+ /** Parsed raw header line with a normalized lookup key. */
28
50
  export interface HeaderLine {
51
+ /** Lower-case header key used for comparisons and lookups. */
29
52
  key: string;
53
+
54
+ /** Full header line, including the original field name, value, and any folded continuations. */
30
55
  line: string;
31
56
  }
32
57
 
58
+ /** Decoded structured header value returned by libmime. */
33
59
  export interface DecodedHeader {
60
+ /** Header key returned by libmime for the decoded value. */
34
61
  key: string;
62
+
63
+ /** Unicode decoded header value. */
35
64
  value: string;
36
65
  }
37
66
 
67
+ /** MIME node emitted by `MessageSplitter` and accepted by `MessageJoiner`. */
38
68
  export interface MimeNode {
69
+ /** Discriminator identifying this chunk as a MIME node. */
39
70
  type: 'node';
71
+
72
+ /** Whether this node is the root message node. */
40
73
  root: boolean;
74
+
75
+ /** Parent MIME node, or `false` for the root node. */
41
76
  parentNode: MimeNode | false;
77
+
78
+ /** Boundary used by this multipart node, or `false` when not multipart. */
42
79
  _boundary: Buffer | false;
80
+
81
+ /** Boundary inherited from the parent multipart node, or `false` when absent. */
43
82
  _parentBoundary: Buffer | false;
83
+
84
+ /** Length, in bytes, of the raw header block collected for this node. */
44
85
  _headerlen: number;
86
+
87
+ /** Multipart subtype such as `mixed` or `alternative`, or `false` for leaf nodes. */
45
88
  multipart: string | false;
89
+
90
+ /** Content-Transfer-Encoding value, normalized to lower case, or `false` when absent. */
46
91
  encoding: string | false;
92
+
93
+ /** Parsed and mutable header collection, available after headers are parsed. */
47
94
  headers: Headers | false;
95
+
96
+ /** MIME content type such as `text/plain`, or `false` when unavailable. */
48
97
  contentType: string | false;
98
+
99
+ /** Charset parameter from Content-Type, or `false` when absent. */
49
100
  charset: string | false;
101
+
102
+ /** Content-Disposition value such as `inline` or `attachment`, or `false` when absent. */
50
103
  disposition: string | false;
104
+
105
+ /** Decoded filename from Content-Disposition or Content-Type parameters, or `false` when absent. */
51
106
  filename: string | false;
107
+
108
+ /** Whether this node is `text/*` with `format=flowed`. */
52
109
  flowed: boolean;
110
+
111
+ /** Whether flowed text uses `delsp=yes`. */
53
112
  delSp: boolean;
113
+
114
+ /** Splitter configuration used when parsing this node. */
54
115
  config: SplitterOptions;
116
+
117
+ /** Resolved IMAP-style part number for this node, or `false` before resolution. */
55
118
  partNr: PartNumber | false;
119
+
120
+ /** Number of child part numbers allocated by this node. */
56
121
  childPartNumbers: number;
122
+
123
+ /** Whether this node's content type is `message/rfc822`. */
57
124
  rfc822: boolean;
125
+
126
+ /** Whether an embedded `message/rfc822` node was parsed as a nested message. */
58
127
  messageNode?: boolean;
59
128
 
129
+ /**
130
+ * Builds the next child part number for this node.
131
+ *
132
+ * @param provided Optional explicit part number item to append.
133
+ * @returns Resolved MIME part number.
134
+ */
60
135
  getPartNr(provided?: PartNumberItem): PartNumber;
136
+
137
+ /**
138
+ * Appends one raw header line to this node while parsing.
139
+ *
140
+ * @param line Raw header line bytes; falsy values are ignored.
141
+ * @returns Nothing.
142
+ */
61
143
  addHeaderChunk(line?: Buffer | false): void;
144
+
145
+ /**
146
+ * Parses collected header bytes and populates MIME metadata fields.
147
+ *
148
+ * @returns Nothing.
149
+ */
62
150
  parseHeaders(): void;
151
+
152
+ /**
153
+ * Builds this node's header block.
154
+ *
155
+ * @returns Header bytes ending with an empty header/body separator line.
156
+ */
63
157
  getHeaders(): Buffer;
158
+
159
+ /**
160
+ * Sets or updates the Content-Type header value.
161
+ *
162
+ * @param contentType MIME content type to set; falsy keeps the current type.
163
+ * @returns Nothing.
164
+ */
64
165
  setContentType(contentType?: string | false): void;
166
+
167
+ /**
168
+ * Sets, updates, or removes the Content-Type charset parameter.
169
+ *
170
+ * @param charset Charset to set; falsy removes it when possible.
171
+ * @returns Nothing.
172
+ */
65
173
  setCharset(charset?: string | false): void;
174
+
175
+ /**
176
+ * Sets, updates, or removes the filename parameter.
177
+ *
178
+ * @param filename Filename to set; falsy removes it when possible.
179
+ * @returns Nothing.
180
+ */
66
181
  setFilename(filename?: string | false): void;
182
+
183
+ /**
184
+ * Creates a decoder stream for this node's transfer encoding.
185
+ *
186
+ * @returns Transform stream that outputs decoded content bytes.
187
+ */
67
188
  getDecoder(): Transform | PassThrough;
189
+
190
+ /**
191
+ * Creates an encoder stream and updates the Content-Transfer-Encoding header when needed.
192
+ *
193
+ * @param encoding Target transfer encoding; defaults to the node's current encoding.
194
+ * @returns Transform stream that outputs encoded content bytes.
195
+ */
68
196
  getEncoder(encoding?: string | false): Transform | PassThrough;
69
197
  }
70
198
 
199
+ /** Data or body bytes emitted by `MessageSplitter`. */
71
200
  export interface MessageChunk {
201
+ /** MIME node that owns or precedes this chunk. */
72
202
  node: MimeNode;
203
+
204
+ /** Chunk kind: multipart structure bytes (`data`) or leaf content bytes (`body`). */
73
205
  type: 'data' | 'body';
206
+
207
+ /** Raw chunk bytes. */
74
208
  value: Buffer;
75
209
  }
76
210
 
211
+ /** Sentinel input used internally to finish a pending rewriter or streamer node. */
77
212
  export interface EmptyChunk {
213
+ /** Discriminator for an empty control chunk. */
78
214
  type: 'none';
79
215
  }
80
216
 
217
+ /** Object emitted by `MessageSplitter`: either a MIME node or a data/body byte chunk. */
81
218
  export type SplitterChunk = MimeNode | MessageChunk;
219
+
220
+ /** Object accepted by rewriter and streamer transforms. */
82
221
  export type RewriterInput = SplitterChunk | EmptyChunk;
222
+
223
+ /**
224
+ * Predicate used to select MIME nodes.
225
+ *
226
+ * @param node MIME node being inspected.
227
+ * @returns `true` to process the node, otherwise `false`.
228
+ */
83
229
  export type FilterFunc = (node: MimeNode) => boolean;
230
+
231
+ /** Error object that may include a Node-style string error code. */
84
232
  export type ErrorWithCode = Error & { code?: string };
233
+
234
+ /**
235
+ * Callback that resumes processing after a selected node stream has ended.
236
+ *
237
+ * @returns Nothing.
238
+ */
85
239
  export type ContinueCallback = () => void;
240
+
241
+ /** Content transform stream used for decoded or encoded node bodies. */
86
242
  export type ContentStream = Transform | PassThrough;
243
+
244
+ /** Decoder stream with an internal readable-state guard used by rewriter/streamer. */
87
245
  export type DecoderStream = ContentStream & { $reading?: boolean };
88
246
 
247
+ /** Internal grouping state used while splitter coalesces adjacent chunks. */
89
248
  export interface SplitterGroup {
249
+ /** MIME node associated with the group, when one exists. */
90
250
  node?: MimeNode;
251
+
252
+ /** Group kind currently being accumulated. */
91
253
  type: 'none' | 'node' | 'data' | 'body';
254
+
255
+ /** Buffered raw bytes for `data` or `body` groups. */
92
256
  value?: Buffer;
93
257
  }
94
258
 
259
+ /** Payload emitted with `NodeRewriter`'s `node` event. */
95
260
  export interface RewriterNode {
261
+ /** Selected MIME node whose body can be rewritten. */
96
262
  node: MimeNode;
263
+
264
+ /** Stream that yields decoded original body bytes. */
97
265
  decoder: Transform;
266
+
267
+ /** Stream that accepts replacement decoded bytes and emits properly encoded body bytes. */
98
268
  encoder: Transform;
99
269
  }
100
270
 
271
+ /** Payload emitted with `NodeStreamer`'s `node` event. */
101
272
  export interface StreamerNode {
273
+ /** Selected MIME node whose body is being streamed. */
102
274
  node: MimeNode;
275
+
276
+ /** Stream that yields decoded original body bytes. */
103
277
  decoder: Transform;
278
+
279
+ /**
280
+ * Signals that the consumer has finished reading the selected node.
281
+ *
282
+ * @returns Nothing.
283
+ */
104
284
  done: () => void;
105
285
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zone-eu/mailsplit",
3
- "version": "5.4.10",
3
+ "version": "5.4.12",
4
4
  "description": "Split email messages into an object stream",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",