imapflow 1.7.8 → 2.0.0

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.
Files changed (296) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +8 -2
  3. package/dist/cjs/charsets.d.ts +1 -0
  4. package/dist/cjs/charsets.js +294 -0
  5. package/dist/cjs/commands/append.d.ts +22 -0
  6. package/dist/cjs/commands/append.js +151 -0
  7. package/dist/cjs/commands/authenticate.d.ts +24 -0
  8. package/dist/cjs/commands/authenticate.js +223 -0
  9. package/dist/cjs/commands/capability.d.ts +8 -0
  10. package/dist/cjs/commands/capability.js +32 -0
  11. package/dist/cjs/commands/close.d.ts +8 -0
  12. package/dist/cjs/commands/close.js +39 -0
  13. package/dist/cjs/commands/compress.d.ts +8 -0
  14. package/dist/cjs/commands/compress.js +56 -0
  15. package/dist/cjs/commands/copy.d.ts +13 -0
  16. package/dist/cjs/commands/copy.js +44 -0
  17. package/dist/cjs/commands/copyuid-parser.d.ts +11 -0
  18. package/dist/cjs/commands/copyuid-parser.js +32 -0
  19. package/dist/cjs/commands/create.d.ts +11 -0
  20. package/dist/cjs/commands/create.js +80 -0
  21. package/dist/cjs/commands/delete.d.ts +11 -0
  22. package/dist/cjs/commands/delete.js +40 -0
  23. package/dist/cjs/commands/enable.d.ts +9 -0
  24. package/dist/cjs/commands/enable.js +61 -0
  25. package/dist/cjs/commands/esearch-parser.d.ts +17 -0
  26. package/dist/cjs/commands/esearch-parser.js +91 -0
  27. package/dist/cjs/commands/expunge.d.ts +12 -0
  28. package/dist/cjs/commands/expunge.js +60 -0
  29. package/dist/cjs/commands/fetch.d.ts +30 -0
  30. package/dist/cjs/commands/fetch.js +241 -0
  31. package/dist/cjs/commands/id.d.ts +10 -0
  32. package/dist/cjs/commands/id.js +80 -0
  33. package/dist/cjs/commands/idle.d.ts +9 -0
  34. package/dist/cjs/commands/idle.js +347 -0
  35. package/dist/cjs/commands/list.d.ts +16 -0
  36. package/dist/cjs/commands/list.js +518 -0
  37. package/dist/cjs/commands/login.d.ts +11 -0
  38. package/dist/cjs/commands/login.js +42 -0
  39. package/dist/cjs/commands/logout.d.ts +8 -0
  40. package/dist/cjs/commands/logout.js +47 -0
  41. package/dist/cjs/commands/move.d.ts +13 -0
  42. package/dist/cjs/commands/move.js +57 -0
  43. package/dist/cjs/commands/namespace.d.ts +25 -0
  44. package/dist/cjs/commands/namespace.js +139 -0
  45. package/dist/cjs/commands/noop.d.ts +8 -0
  46. package/dist/cjs/commands/noop.js +22 -0
  47. package/dist/cjs/commands/quota.d.ts +10 -0
  48. package/dist/cjs/commands/quota.js +119 -0
  49. package/dist/cjs/commands/rename.d.ts +12 -0
  50. package/dist/cjs/commands/rename.js +48 -0
  51. package/dist/cjs/commands/search.d.ts +15 -0
  52. package/dist/cjs/commands/search.js +228 -0
  53. package/dist/cjs/commands/select.d.ts +25 -0
  54. package/dist/cjs/commands/select.js +250 -0
  55. package/dist/cjs/commands/starttls.d.ts +8 -0
  56. package/dist/cjs/commands/starttls.js +30 -0
  57. package/dist/cjs/commands/status-fields.d.ts +14 -0
  58. package/dist/cjs/commands/status-fields.js +61 -0
  59. package/dist/cjs/commands/status.d.ts +12 -0
  60. package/dist/cjs/commands/status.js +108 -0
  61. package/dist/cjs/commands/store.d.ts +19 -0
  62. package/dist/cjs/commands/store.js +93 -0
  63. package/dist/cjs/commands/subscribe.d.ts +9 -0
  64. package/dist/cjs/commands/subscribe.js +31 -0
  65. package/dist/cjs/commands/unsubscribe.d.ts +9 -0
  66. package/dist/cjs/commands/unsubscribe.js +31 -0
  67. package/dist/cjs/connection-deadline.d.ts +49 -0
  68. package/dist/cjs/connection-deadline.js +91 -0
  69. package/dist/cjs/errors.d.ts +83 -0
  70. package/dist/cjs/errors.js +13 -0
  71. package/dist/cjs/handler/imap-compiler.d.ts +24 -0
  72. package/dist/cjs/handler/imap-compiler.js +285 -0
  73. package/dist/cjs/handler/imap-formal-syntax.d.ts +28 -0
  74. package/dist/cjs/handler/imap-formal-syntax.js +121 -0
  75. package/dist/cjs/handler/imap-handler.d.ts +9 -0
  76. package/dist/cjs/handler/imap-handler.js +10 -0
  77. package/dist/cjs/handler/imap-parser.d.ts +16 -0
  78. package/dist/cjs/handler/imap-parser.js +90 -0
  79. package/dist/cjs/handler/imap-stream.d.ts +181 -0
  80. package/dist/cjs/handler/imap-stream.js +446 -0
  81. package/dist/cjs/handler/limits.d.ts +25 -0
  82. package/dist/cjs/handler/limits.js +51 -0
  83. package/dist/cjs/handler/parser-instance.d.ts +68 -0
  84. package/dist/cjs/handler/parser-instance.js +223 -0
  85. package/dist/cjs/handler/token-parser.d.ts +91 -0
  86. package/dist/cjs/handler/token-parser.js +673 -0
  87. package/dist/cjs/handler/types.d.ts +91 -0
  88. package/dist/cjs/handler/types.js +4 -0
  89. package/dist/cjs/imap-commands.d.ts +16 -0
  90. package/dist/cjs/imap-commands.js +74 -0
  91. package/dist/cjs/imap-flow.d.ts +676 -0
  92. package/dist/cjs/imap-flow.js +3949 -0
  93. package/dist/cjs/jp-decoder.d.ts +12 -0
  94. package/dist/cjs/jp-decoder.js +79 -0
  95. package/dist/cjs/limited-passthrough.d.ts +25 -0
  96. package/dist/cjs/limited-passthrough.js +54 -0
  97. package/dist/cjs/logger.d.ts +3 -0
  98. package/dist/cjs/logger.js +11 -0
  99. package/dist/cjs/package-info.d.ts +3 -0
  100. package/dist/cjs/package-info.js +7 -0
  101. package/dist/cjs/package.json +3 -0
  102. package/dist/cjs/proxy-connection.d.ts +33 -0
  103. package/dist/cjs/proxy-connection.js +392 -0
  104. package/dist/cjs/search-compiler.d.ts +34 -0
  105. package/dist/cjs/search-compiler.js +476 -0
  106. package/dist/cjs/special-use.d.ts +22 -0
  107. package/dist/cjs/special-use.js +911 -0
  108. package/dist/cjs/tools.d.ts +427 -0
  109. package/dist/cjs/tools.js +1496 -0
  110. package/{lib/imap-flow.d.ts → dist/cjs/types.d.ts} +386 -516
  111. package/dist/cjs/types.js +5 -0
  112. package/dist/esm/charsets.d.ts +1 -0
  113. package/{lib → dist/esm}/charsets.js +1 -6
  114. package/dist/esm/commands/append.d.ts +22 -0
  115. package/{lib → dist/esm}/commands/append.js +22 -52
  116. package/dist/esm/commands/authenticate.d.ts +24 -0
  117. package/{lib → dist/esm}/commands/authenticate.js +62 -87
  118. package/dist/esm/commands/capability.d.ts +8 -0
  119. package/{lib → dist/esm}/commands/capability.js +6 -9
  120. package/dist/esm/commands/close.d.ts +8 -0
  121. package/{lib → dist/esm}/commands/close.js +6 -10
  122. package/dist/esm/commands/compress.d.ts +8 -0
  123. package/{lib → dist/esm}/commands/compress.js +7 -11
  124. package/dist/esm/commands/copy.d.ts +13 -0
  125. package/{lib → dist/esm}/commands/copy.js +12 -20
  126. package/dist/esm/commands/copyuid-parser.d.ts +11 -0
  127. package/{lib → dist/esm}/commands/copyuid-parser.js +9 -15
  128. package/dist/esm/commands/create.d.ts +11 -0
  129. package/{lib → dist/esm}/commands/create.js +13 -27
  130. package/dist/esm/commands/delete.d.ts +11 -0
  131. package/{lib → dist/esm}/commands/delete.js +9 -14
  132. package/dist/esm/commands/enable.d.ts +9 -0
  133. package/{lib → dist/esm}/commands/enable.js +23 -30
  134. package/dist/esm/commands/esearch-parser.d.ts +17 -0
  135. package/dist/esm/commands/esearch-parser.js +88 -0
  136. package/dist/esm/commands/expunge.d.ts +12 -0
  137. package/{lib → dist/esm}/commands/expunge.js +17 -22
  138. package/dist/esm/commands/fetch.d.ts +30 -0
  139. package/{lib → dist/esm}/commands/fetch.js +32 -64
  140. package/dist/esm/commands/id.d.ts +10 -0
  141. package/{lib → dist/esm}/commands/id.js +17 -23
  142. package/dist/esm/commands/idle.d.ts +9 -0
  143. package/{lib → dist/esm}/commands/idle.js +47 -81
  144. package/dist/esm/commands/list.d.ts +16 -0
  145. package/{lib → dist/esm}/commands/list.js +56 -121
  146. package/dist/esm/commands/login.d.ts +11 -0
  147. package/{lib → dist/esm}/commands/login.js +10 -15
  148. package/dist/esm/commands/logout.d.ts +8 -0
  149. package/{lib → dist/esm}/commands/logout.js +9 -11
  150. package/dist/esm/commands/move.d.ts +13 -0
  151. package/{lib → dist/esm}/commands/move.js +13 -21
  152. package/dist/esm/commands/namespace.d.ts +25 -0
  153. package/{lib → dist/esm}/commands/namespace.js +34 -44
  154. package/dist/esm/commands/noop.d.ts +8 -0
  155. package/{lib → dist/esm}/commands/noop.js +6 -7
  156. package/dist/esm/commands/quota.d.ts +10 -0
  157. package/{lib → dist/esm}/commands/quota.js +18 -36
  158. package/dist/esm/commands/rename.d.ts +12 -0
  159. package/{lib → dist/esm}/commands/rename.js +10 -15
  160. package/dist/esm/commands/search.d.ts +15 -0
  161. package/{lib → dist/esm}/commands/search.js +36 -135
  162. package/dist/esm/commands/select.d.ts +25 -0
  163. package/{lib → dist/esm}/commands/select.js +33 -64
  164. package/dist/esm/commands/starttls.d.ts +8 -0
  165. package/{lib → dist/esm}/commands/starttls.js +6 -8
  166. package/dist/esm/commands/status-fields.d.ts +14 -0
  167. package/{lib → dist/esm}/commands/status-fields.js +5 -16
  168. package/dist/esm/commands/status.d.ts +12 -0
  169. package/{lib → dist/esm}/commands/status.js +18 -29
  170. package/dist/esm/commands/store.d.ts +19 -0
  171. package/{lib → dist/esm}/commands/store.js +24 -37
  172. package/dist/esm/commands/subscribe.d.ts +9 -0
  173. package/{lib → dist/esm}/commands/subscribe.js +8 -12
  174. package/dist/esm/commands/unsubscribe.d.ts +9 -0
  175. package/{lib → dist/esm}/commands/unsubscribe.js +8 -12
  176. package/dist/esm/connection-deadline.d.ts +49 -0
  177. package/{lib → dist/esm}/connection-deadline.js +14 -25
  178. package/dist/esm/errors.d.ts +83 -0
  179. package/dist/esm/errors.js +9 -0
  180. package/dist/esm/handler/imap-compiler.d.ts +24 -0
  181. package/{lib → dist/esm}/handler/imap-compiler.js +22 -80
  182. package/dist/esm/handler/imap-formal-syntax.d.ts +28 -0
  183. package/dist/esm/handler/imap-formal-syntax.js +117 -0
  184. package/dist/esm/handler/imap-handler.d.ts +9 -0
  185. package/dist/esm/handler/imap-handler.js +9 -0
  186. package/dist/esm/handler/imap-parser.d.ts +16 -0
  187. package/{lib → dist/esm}/handler/imap-parser.js +31 -44
  188. package/dist/esm/handler/imap-stream.d.ts +181 -0
  189. package/{lib → dist/esm}/handler/imap-stream.js +29 -121
  190. package/dist/esm/handler/limits.d.ts +25 -0
  191. package/{lib → dist/esm}/handler/limits.js +13 -22
  192. package/dist/esm/handler/parser-instance.d.ts +68 -0
  193. package/{lib → dist/esm}/handler/parser-instance.js +19 -47
  194. package/dist/esm/handler/token-parser.d.ts +91 -0
  195. package/{lib → dist/esm}/handler/token-parser.js +71 -155
  196. package/dist/esm/handler/types.d.ts +91 -0
  197. package/dist/esm/handler/types.js +3 -0
  198. package/dist/esm/imap-commands.d.ts +16 -0
  199. package/dist/esm/imap-commands.js +67 -0
  200. package/dist/esm/imap-flow.d.ts +676 -0
  201. package/{lib → dist/esm}/imap-flow.js +761 -1789
  202. package/dist/esm/jp-decoder.d.ts +12 -0
  203. package/{lib → dist/esm}/jp-decoder.js +6 -21
  204. package/dist/esm/limited-passthrough.d.ts +25 -0
  205. package/{lib → dist/esm}/limited-passthrough.js +7 -20
  206. package/dist/esm/logger.d.ts +3 -0
  207. package/dist/esm/logger.js +4 -0
  208. package/dist/esm/package-info.d.ts +3 -0
  209. package/dist/esm/package-info.js +4 -0
  210. package/dist/esm/package.json +3 -0
  211. package/dist/esm/proxy-connection.d.ts +33 -0
  212. package/{lib → dist/esm}/proxy-connection.js +56 -127
  213. package/dist/esm/search-compiler.d.ts +34 -0
  214. package/{lib → dist/esm}/search-compiler.js +54 -110
  215. package/dist/esm/special-use.d.ts +22 -0
  216. package/dist/esm/special-use.js +907 -0
  217. package/dist/esm/tools.d.ts +427 -0
  218. package/dist/esm/tools.js +1446 -0
  219. package/dist/esm/types.d.ts +828 -0
  220. package/dist/esm/types.js +4 -0
  221. package/package.json +60 -20
  222. package/.gitattributes +0 -1
  223. package/.github/CODE_OF_CONDUCT.md +0 -76
  224. package/.github/FUNDING.yml +0 -4
  225. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  226. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  227. package/.github/contributing.md +0 -17
  228. package/.github/workflows/release.yaml +0 -36
  229. package/.github/workflows/stale.yml +0 -29
  230. package/.github/workflows/test.yml +0 -51
  231. package/.ncurc.js +0 -4
  232. package/.prettierignore +0 -4
  233. package/.prettierrc.js +0 -8
  234. package/.release-please-manifest.json +0 -3
  235. package/CLAUDE.md +0 -104
  236. package/Gruntfile.js +0 -23
  237. package/eslint.config.js +0 -45
  238. package/lib/handler/imap-formal-syntax.js +0 -189
  239. package/lib/handler/imap-handler.js +0 -17
  240. package/lib/imap-commands.js +0 -45
  241. package/lib/logger.js +0 -5
  242. package/lib/special-use.js +0 -923
  243. package/lib/tools.js +0 -1612
  244. package/release-please-config.json +0 -10
  245. package/test/authentication-test.js +0 -101
  246. package/test/auto-idle-test.js +0 -470
  247. package/test/bodystructure-test.js +0 -899
  248. package/test/charsets-test.js +0 -161
  249. package/test/commands-branches-test.js +0 -1095
  250. package/test/commands-integration-test.js +0 -11124
  251. package/test/commands-test.js +0 -73
  252. package/test/connection-edge-cases-test.js +0 -1828
  253. package/test/connection-test.js +0 -162
  254. package/test/copyuid-parser-test.js +0 -173
  255. package/test/fetch-generator-test.js +0 -218
  256. package/test/fixtures/fake-timers.js +0 -115
  257. package/test/fixtures/serialized-mimetorture.js +0 -2738
  258. package/test/fixtures/test-client.js +0 -101
  259. package/test/fixtures/test-tls.js +0 -8
  260. package/test/handler-branches-test.js +0 -310
  261. package/test/idle-polling-test.js +0 -518
  262. package/test/imap-compiler-test.js +0 -809
  263. package/test/imap-flow-compress-test.js +0 -166
  264. package/test/imap-flow-coverage-test.js +0 -612
  265. package/test/imap-flow-fetch-download-test.js +0 -909
  266. package/test/imap-flow-internals-test.js +0 -725
  267. package/test/imap-flow-methods-test.js +0 -889
  268. package/test/imap-flow-proxy-paths-test.js +0 -366
  269. package/test/imap-flow-secure-test.js +0 -573
  270. package/test/imap-flow-server-test.js +0 -1474
  271. package/test/imap-formal-syntax-test.js +0 -293
  272. package/test/imap-parser-test.js +0 -1474
  273. package/test/imap-stream-edge-cases-test.js +0 -666
  274. package/test/imap-stream-test.js +0 -177
  275. package/test/imapflow-test.js +0 -258
  276. package/test/integration/README.md +0 -52
  277. package/test/integration/dovecot-test.conf +0 -27
  278. package/test/integration/rev2-live-test.js +0 -431
  279. package/test/integration/run-rev2-tests.sh +0 -75
  280. package/test/integration-test.js +0 -83
  281. package/test/jp-decoder-test.js +0 -304
  282. package/test/limited-passthrough-test.js +0 -299
  283. package/test/memory-cleanup-test.js +0 -144
  284. package/test/memory-leak-test.js +0 -667
  285. package/test/parser-limits-test.js +0 -292
  286. package/test/proxy-connection-test.js +0 -738
  287. package/test/reliability-improvements-test.js +0 -548
  288. package/test/search-compiler-test.js +0 -1300
  289. package/test/search-test.js +0 -329
  290. package/test/special-use-test.js +0 -418
  291. package/test/starttls-injection-test.js +0 -181
  292. package/test/tag-correlation-test.js +0 -333
  293. package/test/timer-policy-test.js +0 -227
  294. package/test/token-parser-test.js +0 -456
  295. package/test/tools-test.js +0 -2013
  296. package/test/unhandled-rejection-test.js +0 -661
@@ -1,24 +1,19 @@
1
1
  /* eslint new-cap: 0 */
2
-
3
- 'use strict';
4
-
5
- const imapFormalSyntax = require('./imap-formal-syntax');
6
-
7
- const { TokenParser } = require('./token-parser');
8
-
2
+ import imapFormalSyntax from './imap-formal-syntax.js';
3
+ import { TokenParser } from './token-parser.js';
9
4
  /**
10
5
  * Parses a single IMAP response line into its structural components: tag, command,
11
6
  * and attributes. Handles status responses (OK, NO, BAD, PREAUTH, BYE) with their
12
7
  * human-readable text and response codes, as well as continuation responses ("+").
13
8
  */
14
- class ParserInstance {
9
+ export class ParserInstance {
15
10
  /**
16
11
  * Creates a new ParserInstance for parsing an IMAP response line.
17
12
  *
18
- * @param {Buffer|string} input - The raw IMAP response line to parse.
19
- * @param {Object} [options] - Parser options passed through to the TokenParser for attribute parsing.
20
- * @param {boolean} [options.literalPlus] - Whether the LITERAL+ extension is in use.
21
- * @param {Array<Buffer>} [options.literals] - Pre-parsed literal values from the stream.
13
+ * @param input - The raw IMAP response line to parse.
14
+ * @param options - Parser options passed through to the TokenParser for attribute parsing.
15
+ * @param options.literalPlus - Whether the LITERAL+ extension is in use.
16
+ * @param options.literals - Pre-parsed literal values from the stream.
22
17
  */
23
18
  constructor(input, options) {
24
19
  this.input = (input || '').toString();
@@ -26,29 +21,27 @@ class ParserInstance {
26
21
  this.remainder = this.input;
27
22
  this.pos = 0;
28
23
  }
29
-
30
24
  /**
31
25
  * Extracts and returns the IMAP tag from the beginning of the response.
32
26
  * The tag is typically "*" for untagged responses, "+" for continuation requests,
33
27
  * or a client-assigned command tag like "A1".
34
28
  *
35
- * @returns {Promise<string>} The parsed tag string.
29
+ * @returns The parsed tag string.
36
30
  * @throws {Error} If the tag contains invalid characters.
37
31
  */
38
32
  async getTag() {
39
33
  if (!this.tag) {
40
- this.tag = await this.getElement(imapFormalSyntax.tag() + '*+', true);
34
+ this.tag = await this.getElement(imapFormalSyntax.tag() + '*+');
41
35
  }
42
36
  return this.tag;
43
37
  }
44
-
45
38
  /**
46
39
  * Extracts and returns the IMAP command or response name from the input.
47
40
  * For continuation responses (tag "+"), returns an empty string and stores
48
41
  * the remainder as human-readable text. For status responses (OK, NO, BAD,
49
42
  * PREAUTH, BYE), separates the optional response code from the human-readable text.
50
43
  *
51
- * @returns {Promise<string>} The parsed command string.
44
+ * @returns The parsed command string.
52
45
  * @throws {Error} If the command contains invalid characters or input ends unexpectedly.
53
46
  */
54
47
  async getCommand() {
@@ -56,14 +49,11 @@ class ParserInstance {
56
49
  // special case
57
50
  this.humanReadable = this.remainder.trim();
58
51
  this.remainder = '';
59
-
60
52
  return '';
61
53
  }
62
-
63
54
  if (!this.command) {
64
55
  this.command = await this.getElement(imapFormalSyntax.command());
65
56
  }
66
-
67
57
  // Status responses have the format: TAG OK/NO/BAD [response-code] human-readable text
68
58
  // Example: * OK [CAPABILITY IMAP4rev1] Server ready
69
59
  // Example: A1 NO [AUTHENTICATIONFAILED] Invalid credentials
@@ -85,10 +75,10 @@ class ParserInstance {
85
75
  let end = -1;
86
76
  for (let i = match[0].length; i < this.remainder.length; i++) {
87
77
  let c = this.remainder[i];
88
-
89
78
  if (c === '[') {
90
79
  nesting++;
91
- } else if (c === ']') {
80
+ }
81
+ else if (c === ']') {
92
82
  nesting--;
93
83
  }
94
84
  if (!nesting) {
@@ -96,7 +86,6 @@ class ParserInstance {
96
86
  break;
97
87
  }
98
88
  }
99
-
100
89
  // Unbalanced '[' inside the code: the RFC 9051 free-text form
101
90
  // (`atom [SP 1*<any TEXT-CHAR except "]">]`) permits '[' but not
102
91
  // ']', so the code really does end at the first ']' here. Without
@@ -106,40 +95,36 @@ class ParserInstance {
106
95
  if (end < 0) {
107
96
  end = this.remainder.indexOf(']', match[0].length);
108
97
  }
109
-
110
98
  if (end >= 0) {
111
99
  this.humanReadable = this.remainder.substring(end + 1).trim();
112
100
  this.remainder = this.remainder.substring(0, end + 1);
113
101
  }
114
- } else {
102
+ }
103
+ else {
115
104
  this.humanReadable = this.remainder.trim();
116
105
  this.remainder = '';
117
106
  }
118
107
  }
119
108
  break;
120
109
  }
121
-
122
110
  return this.command;
123
111
  }
124
-
125
112
  /**
126
113
  * Extracts the next whitespace-delimited element from the input and validates it
127
114
  * against the given syntax character set. Advances the parser position past the element.
128
115
  *
129
- * @param {string} syntax - A string of allowed characters for the element (as returned by imap-formal-syntax methods).
130
- * @returns {Promise<string>} The extracted element string.
116
+ * @param syntax - A string of allowed characters for the element (as returned by imap-formal-syntax methods).
117
+ * @returns The extracted element string.
131
118
  * @throws {Error} If the element contains characters not in the syntax set, or if input ends unexpectedly.
132
119
  */
133
120
  async getElement(syntax) {
134
121
  let match, element, errPos;
135
-
136
122
  if (/^\s/.test(this.remainder)) {
137
123
  let error = new Error(`Unexpected whitespace at position ${this.pos} [E1]`);
138
124
  error.code = 'ParserError1';
139
125
  error.parserContext = { input: this.input, pos: this.pos };
140
126
  throw error;
141
127
  }
142
-
143
128
  if ((match = this.remainder.match(/^\s*[^\s]+(?=\s|$)/))) {
144
129
  element = match[0];
145
130
  if ((errPos = imapFormalSyntax.verify(element, syntax)) >= 0) {
@@ -162,30 +147,26 @@ class ParserInstance {
162
147
  };
163
148
  throw error;
164
149
  }
165
-
166
150
  let error = new Error(`Unexpected char at position ${this.pos + errPos} [E2: ${JSON.stringify(element.charAt(errPos))}]`);
167
151
  error.code = 'ParserError2';
168
152
  error.parserContext = { input: this.input, element, pos: this.pos };
169
153
  throw error;
170
154
  }
171
- } else {
155
+ }
156
+ else {
172
157
  let error = new Error(`Unexpected end of input at position ${this.pos} [E3]`);
173
158
  error.code = 'ParserError3';
174
159
  error.parserContext = { input: this.input, pos: this.pos };
175
160
  throw error;
176
161
  }
177
-
178
162
  this.pos += match[0].length;
179
163
  this.remainder = this.remainder.substr(match[0].length);
180
-
181
164
  return element;
182
165
  }
183
-
184
166
  /**
185
167
  * Consumes a single space character from the current position in the input.
186
168
  * Advances the parser position by one.
187
169
  *
188
- * @returns {Promise<void>}
189
170
  * @throws {Error} If the current character is not a space, or if input has ended unexpectedly.
190
171
  */
191
172
  async getSpace() {
@@ -194,30 +175,26 @@ class ParserInstance {
194
175
  // special case, empty + response
195
176
  return;
196
177
  }
197
-
198
178
  let error = new Error(`Unexpected end of input at position ${this.pos} [E4]`);
199
179
  error.code = 'ParserError4';
200
180
  error.parserContext = { input: this.input, pos: this.pos };
201
181
  throw error;
202
182
  }
203
-
204
183
  if (imapFormalSyntax.verify(this.remainder.charAt(0), imapFormalSyntax.SP()) >= 0) {
205
184
  let error = new Error(`Unexpected char at position ${this.pos} [E5: ${JSON.stringify(this.remainder.charAt(0))}]`);
206
185
  error.code = 'ParserError5';
207
186
  error.parserContext = { input: this.input, element: this.remainder, pos: this.pos };
208
187
  throw error;
209
188
  }
210
-
211
189
  this.pos++;
212
190
  this.remainder = this.remainder.substr(1);
213
191
  }
214
-
215
192
  /**
216
193
  * Parses the remaining input as IMAP attributes using the TokenParser.
217
194
  * This handles complex structures including nested lists, literals, strings,
218
195
  * atoms, sections, sequences, and partial ranges.
219
196
  *
220
- * @returns {Promise<Array>} A promise that resolves to an array of parsed attribute objects.
197
+ * @returns A promise that resolves to an array of parsed attribute objects.
221
198
  * @throws {Error} If the input contains unexpected whitespace, invalid characters, or ends unexpectedly.
222
199
  */
223
200
  async getAttributes() {
@@ -227,18 +204,13 @@ class ParserInstance {
227
204
  error.parserContext = { input: this.input, pos: this.pos };
228
205
  throw error;
229
206
  }
230
-
231
207
  if (/^\s/.test(this.remainder)) {
232
208
  let error = new Error(`Unexpected whitespace at position ${this.pos} [E7]`);
233
209
  error.code = 'ParserError7';
234
210
  error.parserContext = { input: this.input, element: this.remainder, pos: this.pos };
235
211
  throw error;
236
212
  }
237
-
238
213
  const tokenParser = new TokenParser(this, this.pos, this.remainder, this.options);
239
-
240
214
  return await tokenParser.getAttributes();
241
215
  }
242
216
  }
243
-
244
- module.exports.ParserInstance = ParserInstance;
@@ -0,0 +1,91 @@
1
+ import type { ImapAttributeList, ParserOptions } from './types.js';
2
+ import type { ParserInstance } from './parser-instance.js';
3
+ /**
4
+ * A node of the parse tree built by TokenParser. `type` is false for a node that has not
5
+ * been classified yet, 'TREE' for the root, and otherwise the token or structure type
6
+ * (ATOM, string, LITERAL, SEQUENCE, LIST, SECTION, PARTIAL).
7
+ */
8
+ export interface TokenNode {
9
+ childNodes: TokenNode[];
10
+ type: string | false;
11
+ value: string | Buffer;
12
+ isClosed: boolean;
13
+ parentNode?: TokenNode | undefined;
14
+ depth: number;
15
+ startPos?: number | undefined;
16
+ endPos?: number | undefined;
17
+ literalType?: string | undefined;
18
+ /** Digits accumulated as a string while the literal marker is read, converted to a number once the marker closes */
19
+ literalLength?: string | number | undefined;
20
+ literalPlus?: boolean | undefined;
21
+ started?: boolean | undefined;
22
+ chBuffer?: Buffer | undefined;
23
+ chPos?: number | undefined;
24
+ }
25
+ /**
26
+ * The parent object a TokenParser reads the parsed command from
27
+ */
28
+ export interface TokenParserParent {
29
+ command?: string | undefined;
30
+ }
31
+ /**
32
+ * Tokenizes an IMAP attribute string into a tree of typed nodes.
33
+ * Handles all IMAP data types: atoms, quoted strings, literals (including literal8),
34
+ * sequences, lists (parenthesized groups), sections (bracketed groups), and partial ranges.
35
+ * Enforces a maximum nesting depth of {@link MAX_NODE_DEPTH} to prevent stack overflow
36
+ * from malicious input.
37
+ */
38
+ export declare class TokenParser {
39
+ str: string;
40
+ options: ParserOptions;
41
+ parent: TokenParserParent | ParserInstance;
42
+ maxLiteralSize: number;
43
+ tree: TokenNode;
44
+ currentNode: TokenNode;
45
+ pos: number;
46
+ state: number;
47
+ expectedLiteralType?: string | false | undefined;
48
+ /**
49
+ * Creates a new TokenParser.
50
+ *
51
+ * @param parent - The parent ParserInstance that owns this token parser. Used to access the parsed command for context-sensitive parsing.
52
+ * @param startPos - The starting position offset in the original input, used for error reporting.
53
+ * @param str - The attribute string to tokenize.
54
+ * @param options - Parser options.
55
+ * @param options.literalPlus - Whether the LITERAL+ extension is in use.
56
+ * @param options.literals - Pre-parsed literal values from the input stream.
57
+ * @param options.maxLiteralSize - Maximum size (in bytes) of a literal parsed inline
58
+ * from the input, i.e. when no pre-parsed literal buffers were supplied. Defaults to 1GB.
59
+ */
60
+ constructor(parent: TokenParserParent | ParserInstance, startPos?: number | undefined, str?: string | null | undefined, options?: ParserOptions | undefined);
61
+ /**
62
+ * Processes the input string and returns the parsed attributes as a flat array of typed objects.
63
+ * Each attribute is an object with a `type` (e.g., "ATOM", "STRING", "LITERAL", "SEQUENCE")
64
+ * and a `value` property. Lists are represented as nested arrays. Sections and partials are
65
+ * attached as properties on the preceding attribute object.
66
+ *
67
+ * @returns A promise that resolves to an array of parsed attribute objects and nested arrays.
68
+ * @throws {Error} If the input contains syntax errors or unclosed nodes.
69
+ */
70
+ getAttributes(): Promise<ImapAttributeList>;
71
+ /**
72
+ * Creates a new node in the parse tree. Each node represents a token or structural
73
+ * element (e.g., atom, string, literal, list, section, partial). The node is automatically
74
+ * appended to the parent's childNodes array if a parent is provided.
75
+ *
76
+ * @param parentNode - The parent node to attach this node to. If omitted, creates a root node.
77
+ * @param startPos - The starting position of this node in the original input string.
78
+ * @returns The newly created node with childNodes, type, value, and isClosed properties.
79
+ * @throws {Error} If the nesting depth exceeds MAX_NODE_DEPTH.
80
+ */
81
+ createNode(parentNode?: TokenNode | undefined, startPos?: number | undefined): TokenNode;
82
+ /**
83
+ * Processes the entire input string character by character using a state machine.
84
+ * Transitions between states (NORMAL, ATOM, STRING, LITERAL, SEQUENCE, PARTIAL, TEXT)
85
+ * based on the current character and builds the parse tree. This is the main parsing
86
+ * loop that drives the tokenization.
87
+ *
88
+ * @throws {Error} If the input contains unexpected characters, unclosed structures, or other syntax errors.
89
+ */
90
+ processString(): Promise<void>;
91
+ }