@fluxmail/core 0.14.0 → 0.16.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.
package/dist/errors.d.ts CHANGED
@@ -1,9 +1,39 @@
1
+ import type { Provider } from './types.js';
1
2
  export type EmailErrorCode = 'auth_expired' | 'rate_limited' | 'not_found' | 'invalid_request' | 'idempotency_conflict' | 'provider_unavailable' | 'entitlement_exceeded' | 'permission_denied' | 'unsupported_capability';
3
+ export declare const MAIL_PROVIDERS: readonly Provider[];
4
+ /** Fixed causes for a provider failure. These are safe to report in telemetry. */
5
+ export declare const FAILURE_REASONS: readonly ["search_timeout", "insufficient_scope", "connection_refused", "host_not_found", "network_unreachable", "connection_timeout", "connection_reset", "tls_mismatch", "tls_error", "server_no", "server_bad", "http_error", "invalid_response", "other"];
6
+ export type FailureReason = (typeof FAILURE_REASONS)[number];
7
+ /** The step of a provider call that failed. */
8
+ export declare const FAILURE_PHASES: readonly ["connect", "folders", "select", "search", "fetch", "smtp", "token_refresh", "request"];
9
+ export type FailurePhase = (typeof FAILURE_PHASES)[number];
10
+ /** Node and TLS error codes that describe a network failure without revealing its target. */
11
+ export declare const FAILURE_IO_CODES: readonly ["ECONNREFUSED", "ECONNRESET", "ECONNABORTED", "EPIPE", "ETIMEDOUT", "ENOTFOUND", "EAI_AGAIN", "EHOSTUNREACH", "EHOSTDOWN", "ENETUNREACH", "ENETDOWN", "CERT_HAS_EXPIRED", "DEPTH_ZERO_SELF_SIGNED_CERT", "SELF_SIGNED_CERT_IN_CHAIN", "UNABLE_TO_VERIFY_LEAF_SIGNATURE", "UNABLE_TO_GET_ISSUER_CERT_LOCALLY", "ERR_TLS_CERT_ALTNAME_INVALID", "ERR_SSL_WRONG_VERSION_NUMBER"];
12
+ /**
13
+ * Structured detail about a provider failure. Every field is an allowlisted
14
+ * value, so it can be reported without the error message.
15
+ */
16
+ export interface ProviderFailure {
17
+ provider?: Provider;
18
+ reason?: FailureReason;
19
+ phase?: FailurePhase;
20
+ httpStatus?: number;
21
+ ioCode?: string;
22
+ }
2
23
  export declare class EmailError extends Error {
3
24
  readonly code: EmailErrorCode;
4
25
  /** Machine-readable extras, e.g. { reauthUrl } for auth_expired. */
5
26
  readonly data?: Record<string, unknown>;
6
- constructor(code: EmailErrorCode, message: string, data?: Record<string, unknown>);
27
+ /** Diagnostic detail filled in by the provider and the service as the error propagates. */
28
+ failure?: ProviderFailure;
29
+ constructor(code: EmailErrorCode, message: string, data?: Record<string, unknown>, failure?: ProviderFailure);
7
30
  }
31
+ /**
32
+ * Classify a network or TLS failure from the error codes on an error and its
33
+ * causes. Returns undefined when the error carries no recognized code.
34
+ */
35
+ export declare function networkFailure(error: unknown): Pick<ProviderFailure, 'reason' | 'ioCode'> | undefined;
36
+ /** A provider response is missing data Fluxmail needs. */
37
+ export declare function invalidResponseError(message: string): EmailError;
8
38
  export declare function isEmailError(err: unknown): err is EmailError;
9
39
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,cAAc,GACd,WAAW,GACX,iBAAiB,GACjB,sBAAsB,GACtB,sBAAsB,GACtB,sBAAsB,GACtB,mBAAmB,GACnB,wBAAwB,CAAC;AAE7B,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAE5B,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAMlF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,UAAU,CAE5D"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,cAAc,GACd,WAAW,GACX,iBAAiB,GACjB,sBAAsB,GACtB,sBAAsB,GACtB,sBAAsB,GACtB,mBAAmB,GACnB,wBAAwB,CAAC;AAE7B,eAAO,MAAM,cAAc,EAAE,SAAS,QAAQ,EAAiC,CAAC;AAEhF,kFAAkF;AAClF,eAAO,MAAM,eAAe,+PAelB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,+CAA+C;AAC/C,eAAO,MAAM,cAAc,kGASjB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,yXAmBnB,CAAC;AAEX;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,2FAA2F;IAC3F,OAAO,CAAC,EAAE,eAAe,CAAC;gBAEd,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe;CAO7G;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAAG,SAAS,CAUrG;AAED,0DAA0D;AAC1D,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAEhE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,UAAU,CAE5D"}
package/dist/errors.js CHANGED
@@ -1,14 +1,100 @@
1
+ export const MAIL_PROVIDERS = ['gmail', 'imap', 'outlook'];
2
+ /** Fixed causes for a provider failure. These are safe to report in telemetry. */
3
+ export const FAILURE_REASONS = [
4
+ 'search_timeout',
5
+ 'insufficient_scope',
6
+ 'connection_refused',
7
+ 'host_not_found',
8
+ 'network_unreachable',
9
+ 'connection_timeout',
10
+ 'connection_reset',
11
+ 'tls_mismatch',
12
+ 'tls_error',
13
+ 'server_no',
14
+ 'server_bad',
15
+ 'http_error',
16
+ 'invalid_response',
17
+ 'other',
18
+ ];
19
+ /** The step of a provider call that failed. */
20
+ export const FAILURE_PHASES = [
21
+ 'connect',
22
+ 'folders',
23
+ 'select',
24
+ 'search',
25
+ 'fetch',
26
+ 'smtp',
27
+ 'token_refresh',
28
+ 'request',
29
+ ];
30
+ /** Node and TLS error codes that describe a network failure without revealing its target. */
31
+ export const FAILURE_IO_CODES = [
32
+ 'ECONNREFUSED',
33
+ 'ECONNRESET',
34
+ 'ECONNABORTED',
35
+ 'EPIPE',
36
+ 'ETIMEDOUT',
37
+ 'ENOTFOUND',
38
+ 'EAI_AGAIN',
39
+ 'EHOSTUNREACH',
40
+ 'EHOSTDOWN',
41
+ 'ENETUNREACH',
42
+ 'ENETDOWN',
43
+ 'CERT_HAS_EXPIRED',
44
+ 'DEPTH_ZERO_SELF_SIGNED_CERT',
45
+ 'SELF_SIGNED_CERT_IN_CHAIN',
46
+ 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
47
+ 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
48
+ 'ERR_TLS_CERT_ALTNAME_INVALID',
49
+ 'ERR_SSL_WRONG_VERSION_NUMBER',
50
+ ];
1
51
  export class EmailError extends Error {
2
52
  code;
3
53
  /** Machine-readable extras, e.g. { reauthUrl } for auth_expired. */
4
54
  data;
5
- constructor(code, message, data) {
55
+ /** Diagnostic detail filled in by the provider and the service as the error propagates. */
56
+ failure;
57
+ constructor(code, message, data, failure) {
6
58
  super(message);
7
59
  this.name = 'EmailError';
8
60
  this.code = code;
9
61
  this.data = data;
62
+ if (failure)
63
+ this.failure = failure;
10
64
  }
11
65
  }
66
+ const IO_REASONS = {
67
+ ECONNREFUSED: 'connection_refused',
68
+ ECONNRESET: 'connection_reset',
69
+ ECONNABORTED: 'connection_reset',
70
+ EPIPE: 'connection_reset',
71
+ ETIMEDOUT: 'connection_timeout',
72
+ ENOTFOUND: 'host_not_found',
73
+ EAI_AGAIN: 'host_not_found',
74
+ EHOSTUNREACH: 'network_unreachable',
75
+ EHOSTDOWN: 'network_unreachable',
76
+ ENETUNREACH: 'network_unreachable',
77
+ ENETDOWN: 'network_unreachable',
78
+ };
79
+ /**
80
+ * Classify a network or TLS failure from the error codes on an error and its
81
+ * causes. Returns undefined when the error carries no recognized code.
82
+ */
83
+ export function networkFailure(error) {
84
+ let current = error;
85
+ for (let depth = 0; depth < 4 && current && typeof current === 'object'; depth++) {
86
+ const code = current.code;
87
+ if (typeof code === 'string' && FAILURE_IO_CODES.includes(code)) {
88
+ return { reason: IO_REASONS[code] ?? 'tls_error', ioCode: code };
89
+ }
90
+ current = current.cause;
91
+ }
92
+ return undefined;
93
+ }
94
+ /** A provider response is missing data Fluxmail needs. */
95
+ export function invalidResponseError(message) {
96
+ return new EmailError('provider_unavailable', message, undefined, { reason: 'invalid_response' });
97
+ }
12
98
  export function isEmailError(err) {
13
99
  return err instanceof EmailError;
14
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC1B,IAAI,CAAiB;IAC9B,oEAAoE;IAC3D,IAAI,CAA2B;IAExC,YAAY,IAAoB,EAAE,OAAe,EAAE,IAA8B;QAC/E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,OAAO,GAAG,YAAY,UAAU,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluxmail/core",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "Unified email types and provider interface for Fluxmail",
5
5
  "license": "Elastic-2.0",
6
6
  "repository": {