imapflow 1.7.8 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +8 -2
- package/dist/cjs/charsets.d.ts +1 -0
- package/dist/cjs/charsets.js +294 -0
- package/dist/cjs/commands/append.d.ts +22 -0
- package/dist/cjs/commands/append.js +151 -0
- package/dist/cjs/commands/authenticate.d.ts +24 -0
- package/dist/cjs/commands/authenticate.js +223 -0
- package/dist/cjs/commands/capability.d.ts +8 -0
- package/dist/cjs/commands/capability.js +32 -0
- package/dist/cjs/commands/close.d.ts +8 -0
- package/dist/cjs/commands/close.js +39 -0
- package/dist/cjs/commands/compress.d.ts +8 -0
- package/dist/cjs/commands/compress.js +56 -0
- package/dist/cjs/commands/copy.d.ts +13 -0
- package/dist/cjs/commands/copy.js +44 -0
- package/dist/cjs/commands/copyuid-parser.d.ts +11 -0
- package/dist/cjs/commands/copyuid-parser.js +32 -0
- package/dist/cjs/commands/create.d.ts +11 -0
- package/dist/cjs/commands/create.js +80 -0
- package/dist/cjs/commands/delete.d.ts +11 -0
- package/dist/cjs/commands/delete.js +40 -0
- package/dist/cjs/commands/enable.d.ts +9 -0
- package/dist/cjs/commands/enable.js +61 -0
- package/dist/cjs/commands/esearch-parser.d.ts +17 -0
- package/dist/cjs/commands/esearch-parser.js +91 -0
- package/dist/cjs/commands/expunge.d.ts +12 -0
- package/dist/cjs/commands/expunge.js +60 -0
- package/dist/cjs/commands/fetch.d.ts +30 -0
- package/dist/cjs/commands/fetch.js +241 -0
- package/dist/cjs/commands/id.d.ts +10 -0
- package/dist/cjs/commands/id.js +80 -0
- package/dist/cjs/commands/idle.d.ts +9 -0
- package/dist/cjs/commands/idle.js +347 -0
- package/dist/cjs/commands/list.d.ts +16 -0
- package/dist/cjs/commands/list.js +520 -0
- package/dist/cjs/commands/login.d.ts +11 -0
- package/dist/cjs/commands/login.js +42 -0
- package/dist/cjs/commands/logout.d.ts +8 -0
- package/dist/cjs/commands/logout.js +47 -0
- package/dist/cjs/commands/move.d.ts +13 -0
- package/dist/cjs/commands/move.js +57 -0
- package/dist/cjs/commands/namespace.d.ts +25 -0
- package/dist/cjs/commands/namespace.js +139 -0
- package/dist/cjs/commands/noop.d.ts +8 -0
- package/dist/cjs/commands/noop.js +22 -0
- package/dist/cjs/commands/quota.d.ts +10 -0
- package/dist/cjs/commands/quota.js +119 -0
- package/dist/cjs/commands/rename.d.ts +12 -0
- package/dist/cjs/commands/rename.js +48 -0
- package/dist/cjs/commands/search.d.ts +15 -0
- package/dist/cjs/commands/search.js +228 -0
- package/dist/cjs/commands/select.d.ts +25 -0
- package/dist/cjs/commands/select.js +250 -0
- package/dist/cjs/commands/starttls.d.ts +8 -0
- package/dist/cjs/commands/starttls.js +30 -0
- package/dist/cjs/commands/status-fields.d.ts +14 -0
- package/dist/cjs/commands/status-fields.js +61 -0
- package/dist/cjs/commands/status.d.ts +12 -0
- package/dist/cjs/commands/status.js +108 -0
- package/dist/cjs/commands/store.d.ts +19 -0
- package/dist/cjs/commands/store.js +93 -0
- package/dist/cjs/commands/subscribe.d.ts +9 -0
- package/dist/cjs/commands/subscribe.js +31 -0
- package/dist/cjs/commands/unsubscribe.d.ts +9 -0
- package/dist/cjs/commands/unsubscribe.js +31 -0
- package/dist/cjs/connection-deadline.d.ts +49 -0
- package/dist/cjs/connection-deadline.js +91 -0
- package/dist/cjs/errors.d.ts +83 -0
- package/dist/cjs/errors.js +13 -0
- package/dist/cjs/handler/imap-compiler.d.ts +24 -0
- package/dist/cjs/handler/imap-compiler.js +285 -0
- package/dist/cjs/handler/imap-formal-syntax.d.ts +28 -0
- package/dist/cjs/handler/imap-formal-syntax.js +121 -0
- package/dist/cjs/handler/imap-handler.d.ts +9 -0
- package/dist/cjs/handler/imap-handler.js +10 -0
- package/dist/cjs/handler/imap-parser.d.ts +16 -0
- package/dist/cjs/handler/imap-parser.js +90 -0
- package/dist/cjs/handler/imap-stream.d.ts +181 -0
- package/dist/cjs/handler/imap-stream.js +446 -0
- package/dist/cjs/handler/limits.d.ts +25 -0
- package/dist/cjs/handler/limits.js +51 -0
- package/dist/cjs/handler/parser-instance.d.ts +68 -0
- package/dist/cjs/handler/parser-instance.js +223 -0
- package/dist/cjs/handler/token-parser.d.ts +91 -0
- package/dist/cjs/handler/token-parser.js +673 -0
- package/dist/cjs/handler/types.d.ts +91 -0
- package/dist/cjs/handler/types.js +4 -0
- package/dist/cjs/imap-commands.d.ts +16 -0
- package/dist/cjs/imap-commands.js +74 -0
- package/dist/cjs/imap-flow.d.ts +676 -0
- package/dist/cjs/imap-flow.js +3956 -0
- package/dist/cjs/jp-decoder.d.ts +12 -0
- package/dist/cjs/jp-decoder.js +79 -0
- package/dist/cjs/limited-passthrough.d.ts +25 -0
- package/dist/cjs/limited-passthrough.js +54 -0
- package/dist/cjs/logger.d.ts +3 -0
- package/dist/cjs/logger.js +11 -0
- package/dist/cjs/package-info.d.ts +3 -0
- package/dist/cjs/package-info.js +7 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/proxy-connection.d.ts +33 -0
- package/dist/cjs/proxy-connection.js +392 -0
- package/dist/cjs/search-compiler.d.ts +34 -0
- package/dist/cjs/search-compiler.js +476 -0
- package/dist/cjs/special-use.d.ts +22 -0
- package/dist/cjs/special-use.js +911 -0
- package/dist/cjs/tools.d.ts +427 -0
- package/dist/cjs/tools.js +1496 -0
- package/{lib/imap-flow.d.ts → dist/cjs/types.d.ts} +387 -517
- package/dist/cjs/types.js +5 -0
- package/dist/esm/charsets.d.ts +1 -0
- package/{lib → dist/esm}/charsets.js +1 -6
- package/dist/esm/commands/append.d.ts +22 -0
- package/{lib → dist/esm}/commands/append.js +22 -52
- package/dist/esm/commands/authenticate.d.ts +24 -0
- package/{lib → dist/esm}/commands/authenticate.js +62 -87
- package/dist/esm/commands/capability.d.ts +8 -0
- package/{lib → dist/esm}/commands/capability.js +6 -9
- package/dist/esm/commands/close.d.ts +8 -0
- package/{lib → dist/esm}/commands/close.js +6 -10
- package/dist/esm/commands/compress.d.ts +8 -0
- package/{lib → dist/esm}/commands/compress.js +7 -11
- package/dist/esm/commands/copy.d.ts +13 -0
- package/{lib → dist/esm}/commands/copy.js +12 -20
- package/dist/esm/commands/copyuid-parser.d.ts +11 -0
- package/{lib → dist/esm}/commands/copyuid-parser.js +9 -15
- package/dist/esm/commands/create.d.ts +11 -0
- package/{lib → dist/esm}/commands/create.js +13 -27
- package/dist/esm/commands/delete.d.ts +11 -0
- package/{lib → dist/esm}/commands/delete.js +9 -14
- package/dist/esm/commands/enable.d.ts +9 -0
- package/{lib → dist/esm}/commands/enable.js +23 -30
- package/dist/esm/commands/esearch-parser.d.ts +17 -0
- package/dist/esm/commands/esearch-parser.js +88 -0
- package/dist/esm/commands/expunge.d.ts +12 -0
- package/{lib → dist/esm}/commands/expunge.js +17 -22
- package/dist/esm/commands/fetch.d.ts +30 -0
- package/{lib → dist/esm}/commands/fetch.js +32 -64
- package/dist/esm/commands/id.d.ts +10 -0
- package/{lib → dist/esm}/commands/id.js +17 -23
- package/dist/esm/commands/idle.d.ts +9 -0
- package/{lib → dist/esm}/commands/idle.js +47 -81
- package/dist/esm/commands/list.d.ts +16 -0
- package/{lib → dist/esm}/commands/list.js +60 -123
- package/dist/esm/commands/login.d.ts +11 -0
- package/{lib → dist/esm}/commands/login.js +10 -15
- package/dist/esm/commands/logout.d.ts +8 -0
- package/{lib → dist/esm}/commands/logout.js +9 -11
- package/dist/esm/commands/move.d.ts +13 -0
- package/{lib → dist/esm}/commands/move.js +13 -21
- package/dist/esm/commands/namespace.d.ts +25 -0
- package/{lib → dist/esm}/commands/namespace.js +34 -44
- package/dist/esm/commands/noop.d.ts +8 -0
- package/{lib → dist/esm}/commands/noop.js +6 -7
- package/dist/esm/commands/quota.d.ts +10 -0
- package/{lib → dist/esm}/commands/quota.js +18 -36
- package/dist/esm/commands/rename.d.ts +12 -0
- package/{lib → dist/esm}/commands/rename.js +10 -15
- package/dist/esm/commands/search.d.ts +15 -0
- package/{lib → dist/esm}/commands/search.js +36 -135
- package/dist/esm/commands/select.d.ts +25 -0
- package/{lib → dist/esm}/commands/select.js +33 -64
- package/dist/esm/commands/starttls.d.ts +8 -0
- package/{lib → dist/esm}/commands/starttls.js +6 -8
- package/dist/esm/commands/status-fields.d.ts +14 -0
- package/{lib → dist/esm}/commands/status-fields.js +5 -16
- package/dist/esm/commands/status.d.ts +12 -0
- package/{lib → dist/esm}/commands/status.js +18 -29
- package/dist/esm/commands/store.d.ts +19 -0
- package/{lib → dist/esm}/commands/store.js +24 -37
- package/dist/esm/commands/subscribe.d.ts +9 -0
- package/{lib → dist/esm}/commands/subscribe.js +8 -12
- package/dist/esm/commands/unsubscribe.d.ts +9 -0
- package/{lib → dist/esm}/commands/unsubscribe.js +8 -12
- package/dist/esm/connection-deadline.d.ts +49 -0
- package/{lib → dist/esm}/connection-deadline.js +14 -25
- package/dist/esm/errors.d.ts +83 -0
- package/dist/esm/errors.js +9 -0
- package/dist/esm/handler/imap-compiler.d.ts +24 -0
- package/{lib → dist/esm}/handler/imap-compiler.js +22 -80
- package/dist/esm/handler/imap-formal-syntax.d.ts +28 -0
- package/dist/esm/handler/imap-formal-syntax.js +117 -0
- package/dist/esm/handler/imap-handler.d.ts +9 -0
- package/dist/esm/handler/imap-handler.js +9 -0
- package/dist/esm/handler/imap-parser.d.ts +16 -0
- package/{lib → dist/esm}/handler/imap-parser.js +31 -44
- package/dist/esm/handler/imap-stream.d.ts +181 -0
- package/{lib → dist/esm}/handler/imap-stream.js +29 -121
- package/dist/esm/handler/limits.d.ts +25 -0
- package/{lib → dist/esm}/handler/limits.js +13 -22
- package/dist/esm/handler/parser-instance.d.ts +68 -0
- package/{lib → dist/esm}/handler/parser-instance.js +19 -47
- package/dist/esm/handler/token-parser.d.ts +91 -0
- package/{lib → dist/esm}/handler/token-parser.js +71 -155
- package/dist/esm/handler/types.d.ts +91 -0
- package/dist/esm/handler/types.js +3 -0
- package/dist/esm/imap-commands.d.ts +16 -0
- package/dist/esm/imap-commands.js +67 -0
- package/dist/esm/imap-flow.d.ts +676 -0
- package/{lib → dist/esm}/imap-flow.js +769 -1790
- package/dist/esm/jp-decoder.d.ts +12 -0
- package/{lib → dist/esm}/jp-decoder.js +6 -21
- package/dist/esm/limited-passthrough.d.ts +25 -0
- package/{lib → dist/esm}/limited-passthrough.js +7 -20
- package/dist/esm/logger.d.ts +3 -0
- package/dist/esm/logger.js +4 -0
- package/dist/esm/package-info.d.ts +3 -0
- package/dist/esm/package-info.js +4 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/proxy-connection.d.ts +33 -0
- package/{lib → dist/esm}/proxy-connection.js +56 -127
- package/dist/esm/search-compiler.d.ts +34 -0
- package/{lib → dist/esm}/search-compiler.js +54 -110
- package/dist/esm/special-use.d.ts +22 -0
- package/dist/esm/special-use.js +907 -0
- package/dist/esm/tools.d.ts +427 -0
- package/dist/esm/tools.js +1446 -0
- package/dist/esm/types.d.ts +828 -0
- package/dist/esm/types.js +4 -0
- package/package.json +60 -20
- package/.gitattributes +0 -1
- package/.github/CODE_OF_CONDUCT.md +0 -76
- package/.github/FUNDING.yml +0 -4
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- package/.github/contributing.md +0 -17
- package/.github/workflows/release.yaml +0 -36
- package/.github/workflows/stale.yml +0 -29
- package/.github/workflows/test.yml +0 -51
- package/.ncurc.js +0 -4
- package/.prettierignore +0 -4
- package/.prettierrc.js +0 -8
- package/.release-please-manifest.json +0 -3
- package/CLAUDE.md +0 -104
- package/Gruntfile.js +0 -23
- package/eslint.config.js +0 -45
- package/lib/handler/imap-formal-syntax.js +0 -189
- package/lib/handler/imap-handler.js +0 -17
- package/lib/imap-commands.js +0 -45
- package/lib/logger.js +0 -5
- package/lib/special-use.js +0 -923
- package/lib/tools.js +0 -1612
- package/release-please-config.json +0 -10
- package/test/authentication-test.js +0 -101
- package/test/auto-idle-test.js +0 -470
- package/test/bodystructure-test.js +0 -899
- package/test/charsets-test.js +0 -161
- package/test/commands-branches-test.js +0 -1095
- package/test/commands-integration-test.js +0 -11124
- package/test/commands-test.js +0 -73
- package/test/connection-edge-cases-test.js +0 -1828
- package/test/connection-test.js +0 -162
- package/test/copyuid-parser-test.js +0 -173
- package/test/fetch-generator-test.js +0 -218
- package/test/fixtures/fake-timers.js +0 -115
- package/test/fixtures/serialized-mimetorture.js +0 -2738
- package/test/fixtures/test-client.js +0 -101
- package/test/fixtures/test-tls.js +0 -8
- package/test/handler-branches-test.js +0 -310
- package/test/idle-polling-test.js +0 -518
- package/test/imap-compiler-test.js +0 -809
- package/test/imap-flow-compress-test.js +0 -166
- package/test/imap-flow-coverage-test.js +0 -612
- package/test/imap-flow-fetch-download-test.js +0 -909
- package/test/imap-flow-internals-test.js +0 -725
- package/test/imap-flow-methods-test.js +0 -889
- package/test/imap-flow-proxy-paths-test.js +0 -366
- package/test/imap-flow-secure-test.js +0 -573
- package/test/imap-flow-server-test.js +0 -1474
- package/test/imap-formal-syntax-test.js +0 -293
- package/test/imap-parser-test.js +0 -1474
- package/test/imap-stream-edge-cases-test.js +0 -666
- package/test/imap-stream-test.js +0 -177
- package/test/imapflow-test.js +0 -258
- package/test/integration/README.md +0 -52
- package/test/integration/dovecot-test.conf +0 -27
- package/test/integration/rev2-live-test.js +0 -431
- package/test/integration/run-rev2-tests.sh +0 -75
- package/test/integration-test.js +0 -83
- package/test/jp-decoder-test.js +0 -304
- package/test/limited-passthrough-test.js +0 -299
- package/test/memory-cleanup-test.js +0 -144
- package/test/memory-leak-test.js +0 -667
- package/test/parser-limits-test.js +0 -292
- package/test/proxy-connection-test.js +0 -738
- package/test/reliability-improvements-test.js +0 -548
- package/test/search-compiler-test.js +0 -1300
- package/test/search-test.js +0 -329
- package/test/special-use-test.js +0 -418
- package/test/starttls-injection-test.js +0 -181
- package/test/tag-correlation-test.js +0 -333
- package/test/timer-policy-test.js +0 -227
- package/test/token-parser-test.js +0 -456
- package/test/tools-test.js +0 -2013
- package/test/unhandled-rejection-test.js +0 -661
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { parseBigIntValue, parseUintValue, MAX_UINT32_DIGITS } = require('../tools.js');
|
|
4
|
-
|
|
1
|
+
import { parseBigIntValue, parseUintValue, MAX_UINT32_DIGITS } from '../tools.js';
|
|
5
2
|
// STATUS data items (RFC 3501 section 6.3.10, RFC 7162 for HIGHESTMODSEQ, RFC 9051 for SIZE
|
|
6
3
|
// and DELETED) mapped to the property name each one is exposed under, together with the
|
|
7
4
|
// parser that turns the raw response token into a usable value. Shared by the STATUS command
|
|
@@ -12,8 +9,7 @@ const { parseBigIntValue, parseUintValue, MAX_UINT32_DIGITS } = require('../tool
|
|
|
12
9
|
// mailbox state, where a NaN or a value coerced to Infinity corrupts every later range
|
|
13
10
|
// computation. A plain isNaN() test is not enough: it passes '1e5', ' 12 ' and 'Infinity',
|
|
14
11
|
// and BigInt() throws on all three, aborting the walk over the remaining fields.
|
|
15
|
-
const uint32 = value => parseUintValue(value, MAX_UINT32_DIGITS);
|
|
16
|
-
|
|
12
|
+
const uint32 = (value) => parseUintValue(value, MAX_UINT32_DIGITS);
|
|
17
13
|
const STATUS_FIELDS = {
|
|
18
14
|
MESSAGES: { key: 'messages', parser: uint32 },
|
|
19
15
|
RECENT: { key: 'recent', parser: uint32 },
|
|
@@ -28,41 +24,34 @@ const STATUS_FIELDS = {
|
|
|
28
24
|
SIZE: { key: 'size', parser: value => parseUintValue(value) },
|
|
29
25
|
DELETED: { key: 'deleted', parser: uint32 }
|
|
30
26
|
};
|
|
31
|
-
|
|
32
27
|
/**
|
|
33
28
|
* Walks a STATUS data-item list - alternating item-name and item-value tokens - and reports
|
|
34
29
|
* every recognized field that parsed successfully. Unknown item names and unusable values are
|
|
35
30
|
* skipped, so one bad field never costs the rest of the response.
|
|
36
31
|
*
|
|
37
|
-
* @param
|
|
38
|
-
* @param
|
|
32
|
+
* @param list - Parsed attribute list from the untagged STATUS response.
|
|
33
|
+
* @param onField - Called as (key, value) for each usable field.
|
|
39
34
|
*/
|
|
40
|
-
const parseStatusList = (list, onField) => {
|
|
35
|
+
export const parseStatusList = (list, onField) => {
|
|
41
36
|
let name;
|
|
42
37
|
list.forEach((entry, i) => {
|
|
43
38
|
if (i % 2 === 0) {
|
|
44
39
|
name = entry && typeof entry.value === 'string' ? entry.value : false;
|
|
45
40
|
return;
|
|
46
41
|
}
|
|
47
|
-
|
|
48
42
|
if (!name || !entry) {
|
|
49
43
|
return;
|
|
50
44
|
}
|
|
51
|
-
|
|
52
45
|
// The item name is server-controlled, but uppercasing it before the lookup means no
|
|
53
46
|
// Object.prototype member can be reached: every builtin name has a lowercase letter.
|
|
54
47
|
const field = STATUS_FIELDS[name.toUpperCase()];
|
|
55
48
|
if (!field) {
|
|
56
49
|
return;
|
|
57
50
|
}
|
|
58
|
-
|
|
59
51
|
const value = field.parser(entry.value);
|
|
60
52
|
if (value === false) {
|
|
61
53
|
return;
|
|
62
54
|
}
|
|
63
|
-
|
|
64
55
|
onField(field.key, value);
|
|
65
56
|
});
|
|
66
57
|
};
|
|
67
|
-
|
|
68
|
-
module.exports = { parseStatusList };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ImapFlow } from '../imap-flow.js';
|
|
2
|
+
import type { StatusObject, StatusQuery } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Requests status information about a mailbox.
|
|
5
|
+
*
|
|
6
|
+
* @param connection - IMAP connection instance
|
|
7
|
+
* @param path - Mailbox path to query
|
|
8
|
+
* @param query - Status data items to request (e.g., {messages: true, uidNext: true, unseen: true})
|
|
9
|
+
* @returns Status information object, or false if preconditions not met or on failure
|
|
10
|
+
* @throws {Error} If the mailbox does not exist
|
|
11
|
+
*/
|
|
12
|
+
export default function status(connection: ImapFlow, path: string | string[], query: StatusQuery | undefined): Promise<StatusObject | false>;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { encodePath, normalizePath, buildStatusQueryAttributes, isRev2Active } = require('../tools.js');
|
|
4
|
-
const { parseStatusList } = require('./status-fields.js');
|
|
5
|
-
|
|
1
|
+
import { encodePath, normalizePath, buildStatusQueryAttributes, isRev2Active } from '../tools.js';
|
|
2
|
+
import { parseStatusList } from './status-fields.js';
|
|
6
3
|
// STATUS fields that also refresh the live mailbox state when the queried mailbox is the
|
|
7
4
|
// currently selected one. Keyed by the output property name parseStatusList() reports.
|
|
8
5
|
const MAILBOX_UPDATERS = {
|
|
9
6
|
messages: (value, connection, path) => {
|
|
10
|
-
let
|
|
7
|
+
let mailbox = connection.mailbox;
|
|
8
|
+
let prevCount = mailbox.exists;
|
|
11
9
|
if (prevCount !== value) {
|
|
12
|
-
|
|
10
|
+
mailbox.exists = value;
|
|
13
11
|
connection.emit('exists', { path, count: value, prevCount });
|
|
14
12
|
}
|
|
15
13
|
},
|
|
@@ -20,45 +18,37 @@ const MAILBOX_UPDATERS = {
|
|
|
20
18
|
connection.mailbox.highestModseq = value;
|
|
21
19
|
}
|
|
22
20
|
};
|
|
23
|
-
|
|
24
21
|
/**
|
|
25
22
|
* Requests status information about a mailbox.
|
|
26
23
|
*
|
|
27
|
-
* @param
|
|
28
|
-
* @param
|
|
29
|
-
* @param
|
|
30
|
-
* @returns
|
|
24
|
+
* @param connection - IMAP connection instance
|
|
25
|
+
* @param path - Mailbox path to query
|
|
26
|
+
* @param query - Status data items to request (e.g., {messages: true, uidNext: true, unseen: true})
|
|
27
|
+
* @returns Status information object, or false if preconditions not met or on failure
|
|
31
28
|
* @throws {Error} If the mailbox does not exist
|
|
32
29
|
*/
|
|
33
|
-
|
|
30
|
+
export default async function status(connection, path, query) {
|
|
34
31
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !path) {
|
|
35
32
|
// nothing to do here
|
|
36
33
|
return false;
|
|
37
34
|
}
|
|
38
|
-
|
|
39
35
|
path = normalizePath(connection, path);
|
|
40
36
|
let encodedPath = encodePath(connection, path);
|
|
41
|
-
|
|
42
37
|
// Use quoted STRING if the encoded path contains '&' (modified UTF-7 marker),
|
|
43
38
|
// otherwise use unquoted ATOM. Same approach as in SELECT.
|
|
44
39
|
let attributes = [{ type: encodedPath.indexOf('&') >= 0 ? 'STRING' : 'ATOM', value: encodedPath }];
|
|
45
|
-
|
|
46
40
|
// Build the list of STATUS data items the caller wants
|
|
47
41
|
let queryAttributes = buildStatusQueryAttributes(connection, query);
|
|
48
|
-
|
|
49
42
|
// RECENT does not exist in IMAP4rev2 so it is never requested from a rev2
|
|
50
43
|
// session; its defined value there is always 0. Synthesizing it keeps the
|
|
51
44
|
// return shape identical to a rev1 session for the same query.
|
|
52
45
|
let syntheticRecent = query && query.recent && isRev2Active(connection);
|
|
53
|
-
|
|
54
46
|
if (!queryAttributes.length) {
|
|
55
47
|
// A query that only contained items unavailable on this session - the
|
|
56
48
|
// caller still gets a status object if every such item has a defined value
|
|
57
49
|
return syntheticRecent ? { path, recent: 0 } : false;
|
|
58
50
|
}
|
|
59
|
-
|
|
60
51
|
attributes.push(queryAttributes);
|
|
61
|
-
|
|
62
52
|
let response;
|
|
63
53
|
try {
|
|
64
54
|
let map = { path };
|
|
@@ -66,20 +56,19 @@ module.exports = async (connection, path, query) => {
|
|
|
66
56
|
untagged: {
|
|
67
57
|
// STATUS response: * STATUS <mailbox> (<key> <value> <key> <value> ...)
|
|
68
58
|
// Parsed as alternating key-value pairs (i % 2 pattern).
|
|
69
|
-
STATUS: async untagged => {
|
|
59
|
+
STATUS: async (untagged) => {
|
|
70
60
|
// If querying the currently selected mailbox, also update the
|
|
71
61
|
// connection's live mailbox state and emit events for changes.
|
|
72
62
|
let updateCurrent = connection.state === connection.states.SELECTED && path === connection.mailbox.path;
|
|
73
|
-
|
|
74
63
|
let list = untagged.attributes && Array.isArray(untagged.attributes[1]) ? untagged.attributes[1] : false;
|
|
75
64
|
if (!list) {
|
|
76
65
|
return;
|
|
77
66
|
}
|
|
78
67
|
parseStatusList(list, (key, value) => {
|
|
79
68
|
map[key] = value;
|
|
80
|
-
|
|
81
|
-
if (updateCurrent &&
|
|
82
|
-
|
|
69
|
+
let updater = MAILBOX_UPDATERS[key];
|
|
70
|
+
if (updateCurrent && updater) {
|
|
71
|
+
updater(value, connection, path);
|
|
83
72
|
}
|
|
84
73
|
});
|
|
85
74
|
}
|
|
@@ -90,9 +79,10 @@ module.exports = async (connection, path, query) => {
|
|
|
90
79
|
map.recent = 0;
|
|
91
80
|
}
|
|
92
81
|
return map;
|
|
93
|
-
}
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
94
84
|
// A NO response usually means the mailbox doesn't exist. Verify by
|
|
95
|
-
// running LIST
|
|
85
|
+
// running LIST: if no results, throw a clear NotFound error instead
|
|
96
86
|
// of the generic IMAP error.
|
|
97
87
|
// Note: this uses run(), so when STATUS was dispatched by fallback polling through
|
|
98
88
|
// runInternal() the LIST awaits that polling session's own preCheck and cancels it.
|
|
@@ -107,8 +97,7 @@ module.exports = async (connection, path, query) => {
|
|
|
107
97
|
throw error;
|
|
108
98
|
}
|
|
109
99
|
}
|
|
110
|
-
|
|
111
100
|
connection.log.warn({ err, cid: connection.id });
|
|
112
101
|
return false;
|
|
113
102
|
}
|
|
114
|
-
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ImapFlow } from '../imap-flow.js';
|
|
2
|
+
import type { StoreOptions } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Options for the STORE command
|
|
5
|
+
*/
|
|
6
|
+
export interface StoreCommandOptions extends StoreOptions {
|
|
7
|
+
/** Operation type: 'set', 'add', or 'remove' */
|
|
8
|
+
operation?: string | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Updates flags or labels for messages in the selected mailbox.
|
|
12
|
+
*
|
|
13
|
+
* @param connection - IMAP connection instance
|
|
14
|
+
* @param range - Message sequence number or UID range
|
|
15
|
+
* @param flags - Flag(s) to set, add, or remove
|
|
16
|
+
* @param options - Store options
|
|
17
|
+
* @returns True on success, false on failure or if nothing to do
|
|
18
|
+
*/
|
|
19
|
+
export default function store(connection: ImapFlow, range: string, flags: string | string[], options: StoreCommandOptions): Promise<boolean>;
|
|
@@ -1,43 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { formatFlag, canUseFlag, enhanceCommandError } = require('../tools.js');
|
|
4
|
-
|
|
1
|
+
import { formatFlag, canUseFlag, enhanceCommandError } from '../tools.js';
|
|
5
2
|
/**
|
|
6
3
|
* Updates flags or labels for messages in the selected mailbox.
|
|
7
4
|
*
|
|
8
|
-
* @param
|
|
9
|
-
* @param
|
|
10
|
-
* @param
|
|
11
|
-
* @param
|
|
12
|
-
* @
|
|
13
|
-
* @param {boolean} [options.useLabels] - If true, operate on Gmail labels instead of flags
|
|
14
|
-
* @param {boolean} [options.silent] - If true, use .SILENT variant to suppress server response
|
|
15
|
-
* @param {string} [options.operation] - Operation type: 'set', 'add', or 'remove'
|
|
16
|
-
* @param {string} [options.unchangedSince] - Only update messages not changed since this modseq value
|
|
17
|
-
* @returns {Promise<boolean>} True on success, false on failure or if nothing to do
|
|
5
|
+
* @param connection - IMAP connection instance
|
|
6
|
+
* @param range - Message sequence number or UID range
|
|
7
|
+
* @param flags - Flag(s) to set, add, or remove
|
|
8
|
+
* @param options - Store options
|
|
9
|
+
* @returns True on success, false on failure or if nothing to do
|
|
18
10
|
*/
|
|
19
|
-
|
|
11
|
+
export default async function store(connection, range, flags, options) {
|
|
20
12
|
if (connection.state !== connection.states.SELECTED || !range || (options.useLabels && !connection.capabilities.has('X-GM-EXT-1'))) {
|
|
21
13
|
// nothing to do here
|
|
22
14
|
return false;
|
|
23
15
|
}
|
|
24
|
-
|
|
25
16
|
/* c8 ignore next */ // options.useLabels is dereferenced in the guard above, so options is always defined here
|
|
26
17
|
options = options || {};
|
|
27
|
-
|
|
28
18
|
// Build the IMAP STORE operation name. The format is:
|
|
29
19
|
// [+|-]FLAGS[.SILENT] or [+|-]X-GM-LABELS
|
|
30
20
|
// Where: no prefix = replace all, + = add, - = remove
|
|
31
21
|
// .SILENT suppresses the server from sending back updated flags (saves bandwidth).
|
|
32
22
|
let operation = 'FLAGS';
|
|
33
|
-
|
|
34
23
|
if (options.useLabels) {
|
|
35
24
|
// Gmail labels (X-GM-EXT-1 extension): operates on labels instead of IMAP flags
|
|
36
25
|
operation = 'X-GM-LABELS';
|
|
37
|
-
}
|
|
26
|
+
}
|
|
27
|
+
else if (options.silent) {
|
|
38
28
|
operation = `${operation}.SILENT`;
|
|
39
29
|
}
|
|
40
|
-
|
|
41
30
|
// Prefix determines the operation: none = set (replace), + = add, - = remove
|
|
42
31
|
switch ((options.operation || '').toLowerCase()) {
|
|
43
32
|
case 'set':
|
|
@@ -50,29 +39,27 @@ module.exports = async (connection, range, flags, options) => {
|
|
|
50
39
|
operation = `+${operation}`;
|
|
51
40
|
break;
|
|
52
41
|
}
|
|
53
|
-
|
|
54
42
|
// Validate each flag: format it (normalize backslash prefix for system flags),
|
|
55
43
|
// then check if the mailbox's permanentFlags allow it. Removal is always allowed
|
|
56
44
|
// since it doesn't require the flag to be in permanentFlags.
|
|
57
45
|
flags = (Array.isArray(flags) ? flags : [].concat(flags || []))
|
|
58
46
|
.map(flag => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
})
|
|
67
|
-
.filter(flag => flag);
|
|
68
|
-
|
|
47
|
+
let formatted = formatFlag(flag);
|
|
48
|
+
if (!canUseFlag(connection.mailbox, formatted) && options.operation !== 'remove') {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return formatted;
|
|
52
|
+
})
|
|
53
|
+
.filter((flag) => !!flag);
|
|
69
54
|
// Allow empty flags only for 'set' operation (which clears all flags)
|
|
70
55
|
if (!flags.length && options.operation !== 'set') {
|
|
71
56
|
return false;
|
|
72
57
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
58
|
+
let attributes = [
|
|
59
|
+
{ type: 'SEQUENCE', value: range },
|
|
60
|
+
{ type: 'ATOM', value: operation },
|
|
61
|
+
flags.map(flag => ({ type: 'ATOM', value: flag }))
|
|
62
|
+
];
|
|
76
63
|
// CONDSTORE (RFC 7162): UNCHANGEDSINCE modifier prevents updating messages whose
|
|
77
64
|
// mod-sequence is higher than the specified value, avoiding overwriting concurrent changes.
|
|
78
65
|
if (options.unchangedSince && connection.enabled.has('CONDSTORE') && !connection.mailbox.noModseq) {
|
|
@@ -87,15 +74,15 @@ module.exports = async (connection, range, flags, options) => {
|
|
|
87
74
|
}
|
|
88
75
|
]);
|
|
89
76
|
}
|
|
90
|
-
|
|
91
77
|
let response;
|
|
92
78
|
try {
|
|
93
79
|
response = await connection.exec(options.uid ? 'UID STORE' : 'STORE', attributes);
|
|
94
80
|
response.next();
|
|
95
81
|
return true;
|
|
96
|
-
}
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
97
84
|
await enhanceCommandError(err);
|
|
98
85
|
connection.log.warn({ err, cid: connection.id });
|
|
99
86
|
return false;
|
|
100
87
|
}
|
|
101
|
-
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ImapFlow } from '../imap-flow.js';
|
|
2
|
+
/**
|
|
3
|
+
* Subscribes to a mailbox.
|
|
4
|
+
*
|
|
5
|
+
* @param connection - IMAP connection instance
|
|
6
|
+
* @param path - Mailbox path to subscribe to
|
|
7
|
+
* @returns True on success, false on failure, or undefined if preconditions not met
|
|
8
|
+
*/
|
|
9
|
+
export default function subscribe(connection: ImapFlow, path: string | string[]): Promise<boolean | undefined>;
|
|
@@ -1,30 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { encodePath, normalizePath, enhanceCommandError } = require('../tools.js');
|
|
4
|
-
|
|
1
|
+
import { encodePath, normalizePath, enhanceCommandError } from '../tools.js';
|
|
5
2
|
/**
|
|
6
3
|
* Subscribes to a mailbox.
|
|
7
4
|
*
|
|
8
|
-
* @param
|
|
9
|
-
* @param
|
|
10
|
-
* @returns
|
|
5
|
+
* @param connection - IMAP connection instance
|
|
6
|
+
* @param path - Mailbox path to subscribe to
|
|
7
|
+
* @returns True on success, false on failure, or undefined if preconditions not met
|
|
11
8
|
*/
|
|
12
|
-
|
|
9
|
+
export default async function subscribe(connection, path) {
|
|
13
10
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
14
11
|
// nothing to do here
|
|
15
12
|
return;
|
|
16
13
|
}
|
|
17
|
-
|
|
18
14
|
path = normalizePath(connection, path);
|
|
19
|
-
|
|
20
15
|
let response;
|
|
21
16
|
try {
|
|
22
17
|
response = await connection.exec('SUBSCRIBE', [{ type: 'ATOM', value: encodePath(connection, path) }]);
|
|
23
18
|
response.next();
|
|
24
19
|
return true;
|
|
25
|
-
}
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
26
22
|
await enhanceCommandError(err);
|
|
27
23
|
connection.log.warn({ err, cid: connection.id });
|
|
28
24
|
return false;
|
|
29
25
|
}
|
|
30
|
-
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ImapFlow } from '../imap-flow.js';
|
|
2
|
+
/**
|
|
3
|
+
* Unsubscribes from a mailbox.
|
|
4
|
+
*
|
|
5
|
+
* @param connection - IMAP connection instance
|
|
6
|
+
* @param path - Mailbox path to unsubscribe from
|
|
7
|
+
* @returns True on success, false on failure, or undefined if preconditions not met
|
|
8
|
+
*/
|
|
9
|
+
export default function unsubscribe(connection: ImapFlow, path: string | string[]): Promise<boolean | undefined>;
|
|
@@ -1,30 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { encodePath, normalizePath, enhanceCommandError } = require('../tools.js');
|
|
4
|
-
|
|
1
|
+
import { encodePath, normalizePath, enhanceCommandError } from '../tools.js';
|
|
5
2
|
/**
|
|
6
3
|
* Unsubscribes from a mailbox.
|
|
7
4
|
*
|
|
8
|
-
* @param
|
|
9
|
-
* @param
|
|
10
|
-
* @returns
|
|
5
|
+
* @param connection - IMAP connection instance
|
|
6
|
+
* @param path - Mailbox path to unsubscribe from
|
|
7
|
+
* @returns True on success, false on failure, or undefined if preconditions not met
|
|
11
8
|
*/
|
|
12
|
-
|
|
9
|
+
export default async function unsubscribe(connection, path) {
|
|
13
10
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
14
11
|
// nothing to do here
|
|
15
12
|
return;
|
|
16
13
|
}
|
|
17
|
-
|
|
18
14
|
path = normalizePath(connection, path);
|
|
19
|
-
|
|
20
15
|
let response;
|
|
21
16
|
try {
|
|
22
17
|
response = await connection.exec('UNSUBSCRIBE', [{ type: 'ATOM', value: encodePath(connection, path) }]);
|
|
23
18
|
response.next();
|
|
24
19
|
return true;
|
|
25
|
-
}
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
26
22
|
await enhanceCommandError(err);
|
|
27
23
|
connection.log.warn({ err, cid: connection.id });
|
|
28
24
|
return false;
|
|
29
25
|
}
|
|
30
|
-
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ImapFlowError } from './errors.js';
|
|
2
|
+
export declare const CONNECT_TIMEOUT: number;
|
|
3
|
+
/**
|
|
4
|
+
* One deadline for an entire connection attempt.
|
|
5
|
+
*
|
|
6
|
+
* DNS resolution, proxy negotiation and the transport handshake all draw from the same budget, so
|
|
7
|
+
* a phase that stalls cannot extend the documented `connectionTimeout`. Every expiry - whether it
|
|
8
|
+
* comes from this deadline or is normalized from a dependency - is reported with the same
|
|
9
|
+
* `CONNECT_TIMEOUT` error shape, so callers do not need to know which phase was blocked.
|
|
10
|
+
*/
|
|
11
|
+
export declare class ConnectionDeadline {
|
|
12
|
+
timeout: number;
|
|
13
|
+
startedAt: number;
|
|
14
|
+
/**
|
|
15
|
+
* @param timeout Configured connection timeout in milliseconds. Normalized once
|
|
16
|
+
* here; 0 and any other falsy or invalid value fall back to the 90 second default.
|
|
17
|
+
*/
|
|
18
|
+
constructor(timeout?: number | string | undefined);
|
|
19
|
+
/**
|
|
20
|
+
* @returns Milliseconds left in the budget, never negative.
|
|
21
|
+
*/
|
|
22
|
+
remaining(): number;
|
|
23
|
+
/**
|
|
24
|
+
* @returns The shared `CONNECT_TIMEOUT` error.
|
|
25
|
+
*/
|
|
26
|
+
error(): ImapFlowError;
|
|
27
|
+
/**
|
|
28
|
+
* Maps a dependency's own expiry onto the shared `CONNECT_TIMEOUT` shape, so callers see one
|
|
29
|
+
* timeout error whichever layer noticed first. The original error is kept as `_err`. Anything
|
|
30
|
+
* that is not a timeout is returned unchanged.
|
|
31
|
+
*
|
|
32
|
+
* @param err Error raised by a dependency during a connection phase.
|
|
33
|
+
* @returns Either the normalized timeout error or the original error.
|
|
34
|
+
*/
|
|
35
|
+
normalize<T extends ImapFlowError | null | undefined>(err: T): T | ImapFlowError;
|
|
36
|
+
/**
|
|
37
|
+
* Throws before a phase is started if the budget is already used up, so no work is begun
|
|
38
|
+
* that could only ever time out.
|
|
39
|
+
*/
|
|
40
|
+
check(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Races a phase against the remaining budget. The timer is always cleared, so a completed
|
|
43
|
+
* phase never leaves a pending timer behind.
|
|
44
|
+
*
|
|
45
|
+
* @param promise Phase to run under the deadline.
|
|
46
|
+
* @returns Resolves with the phase result, rejects with `CONNECT_TIMEOUT`.
|
|
47
|
+
*/
|
|
48
|
+
race<T>(promise: Promise<T>): Promise<T>;
|
|
49
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { clearTimer } from './tools.js';
|
|
3
2
|
// Default upper bound for establishing a usable transport, including DNS and proxy negotiation.
|
|
4
|
-
const CONNECT_TIMEOUT = 90 * 1000;
|
|
5
|
-
|
|
3
|
+
export const CONNECT_TIMEOUT = 90 * 1000;
|
|
6
4
|
/**
|
|
7
5
|
* One deadline for an entire connection attempt.
|
|
8
6
|
*
|
|
@@ -11,25 +9,23 @@ const CONNECT_TIMEOUT = 90 * 1000;
|
|
|
11
9
|
* comes from this deadline or is normalized from a dependency - is reported with the same
|
|
12
10
|
* `CONNECT_TIMEOUT` error shape, so callers do not need to know which phase was blocked.
|
|
13
11
|
*/
|
|
14
|
-
class ConnectionDeadline {
|
|
12
|
+
export class ConnectionDeadline {
|
|
15
13
|
/**
|
|
16
|
-
* @param
|
|
14
|
+
* @param timeout Configured connection timeout in milliseconds. Normalized once
|
|
17
15
|
* here; 0 and any other falsy or invalid value fall back to the 90 second default.
|
|
18
16
|
*/
|
|
19
17
|
constructor(timeout) {
|
|
20
18
|
this.timeout = Number(timeout) || CONNECT_TIMEOUT;
|
|
21
19
|
this.startedAt = Date.now();
|
|
22
20
|
}
|
|
23
|
-
|
|
24
21
|
/**
|
|
25
|
-
* @returns
|
|
22
|
+
* @returns Milliseconds left in the budget, never negative.
|
|
26
23
|
*/
|
|
27
24
|
remaining() {
|
|
28
25
|
return Math.max(0, this.timeout - (Date.now() - this.startedAt));
|
|
29
26
|
}
|
|
30
|
-
|
|
31
27
|
/**
|
|
32
|
-
* @returns
|
|
28
|
+
* @returns The shared `CONNECT_TIMEOUT` error.
|
|
33
29
|
*/
|
|
34
30
|
error() {
|
|
35
31
|
let err = new Error('Failed to establish connection in required time');
|
|
@@ -37,30 +33,26 @@ class ConnectionDeadline {
|
|
|
37
33
|
err.details = { connectionTimeout: this.timeout };
|
|
38
34
|
return err;
|
|
39
35
|
}
|
|
40
|
-
|
|
41
36
|
/**
|
|
42
37
|
* Maps a dependency's own expiry onto the shared `CONNECT_TIMEOUT` shape, so callers see one
|
|
43
38
|
* timeout error whichever layer noticed first. The original error is kept as `_err`. Anything
|
|
44
39
|
* that is not a timeout is returned unchanged.
|
|
45
40
|
*
|
|
46
|
-
* @param
|
|
47
|
-
* @returns
|
|
41
|
+
* @param err Error raised by a dependency during a connection phase.
|
|
42
|
+
* @returns Either the normalized timeout error or the original error.
|
|
48
43
|
*/
|
|
49
44
|
normalize(err) {
|
|
50
45
|
if (!err || err.code === 'CONNECT_TIMEOUT') {
|
|
51
46
|
return err;
|
|
52
47
|
}
|
|
53
|
-
|
|
54
48
|
// The `socks` client reports its own expiry as "Proxy connection timed out"
|
|
55
49
|
if (err.code !== 'ETIMEDOUT' && !/timed out/i.test(err.message || '')) {
|
|
56
50
|
return err;
|
|
57
51
|
}
|
|
58
|
-
|
|
59
52
|
let normalized = this.error();
|
|
60
53
|
normalized._err = err;
|
|
61
54
|
return normalized;
|
|
62
55
|
}
|
|
63
|
-
|
|
64
56
|
/**
|
|
65
57
|
* Throws before a phase is started if the budget is already used up, so no work is begun
|
|
66
58
|
* that could only ever time out.
|
|
@@ -70,29 +62,26 @@ class ConnectionDeadline {
|
|
|
70
62
|
throw this.error();
|
|
71
63
|
}
|
|
72
64
|
}
|
|
73
|
-
|
|
74
65
|
/**
|
|
75
66
|
* Races a phase against the remaining budget. The timer is always cleared, so a completed
|
|
76
67
|
* phase never leaves a pending timer behind.
|
|
77
68
|
*
|
|
78
|
-
* @param
|
|
79
|
-
* @returns
|
|
69
|
+
* @param promise Phase to run under the deadline.
|
|
70
|
+
* @returns Resolves with the phase result, rejects with `CONNECT_TIMEOUT`.
|
|
80
71
|
*/
|
|
81
72
|
async race(promise) {
|
|
82
73
|
this.check();
|
|
83
|
-
|
|
84
74
|
let timer = null;
|
|
85
75
|
try {
|
|
86
76
|
return await Promise.race([
|
|
87
77
|
promise,
|
|
88
|
-
new Promise((
|
|
78
|
+
new Promise((_resolve, reject) => {
|
|
89
79
|
timer = setTimeout(() => reject(this.error()), this.remaining());
|
|
90
80
|
})
|
|
91
81
|
]);
|
|
92
|
-
}
|
|
93
|
-
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
clearTimer(timer);
|
|
94
85
|
}
|
|
95
86
|
}
|
|
96
87
|
}
|
|
97
|
-
|
|
98
|
-
module.exports = { ConnectionDeadline, CONNECT_TIMEOUT };
|