@bernierllc/email-domain-verification 1.1.0 → 3.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.
- package/dist/EmailDomainVerificationService.js +5 -0
- package/dist/errors.d.ts +20 -9
- package/dist/errors.js +35 -15
- package/package.json +9 -5
- package/.eslintrc.cjs +0 -29
- package/CHANGELOG.md +0 -121
- package/__mocks__/@bernierllc/crypto-utils.ts +0 -15
- package/__mocks__/@bernierllc/logger.ts +0 -42
- package/__mocks__/@bernierllc/neverhub-adapter.ts +0 -17
- package/__tests__/EmailDomainVerificationService.test.ts +0 -582
- package/__tests__/coverage-gaps.test.ts +0 -566
- package/jest.config.cjs +0 -44
- package/jest.setup.js +0 -19
- package/src/EmailDomainVerificationService.ts +0 -998
- package/src/dns2.d.ts +0 -29
- package/src/errors.ts +0 -79
- package/src/index.ts +0 -11
- package/src/types.ts +0 -281
- package/tsconfig.json +0 -30
|
@@ -26,6 +26,11 @@ const errors_1 = require("./errors");
|
|
|
26
26
|
* DNS record generation, propagation monitoring, and health checks.
|
|
27
27
|
*/
|
|
28
28
|
class EmailDomainVerificationService {
|
|
29
|
+
logger;
|
|
30
|
+
neverhub;
|
|
31
|
+
httpClient;
|
|
32
|
+
healthCheckJobs;
|
|
33
|
+
verificationHistory;
|
|
29
34
|
constructor(config) {
|
|
30
35
|
this.logger = config?.logger || new logger_1.Logger({
|
|
31
36
|
level: logger_1.LogLevel.INFO,
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Domain verification error
|
|
2
|
+
* Domain verification error codes (string literal union — discriminating code values).
|
|
3
|
+
*/
|
|
4
|
+
export type DomainVerificationErrorCode = 'DOMAIN_VERIFICATION_ERROR' | 'DNS_PROPAGATION_ERROR' | 'PROVIDER_API_ERROR' | 'INVALID_DOMAIN' | 'INVALID_INPUT' | 'OPERATION_FAILED';
|
|
5
|
+
export interface DomainVerificationErrorOptions {
|
|
6
|
+
cause?: Error;
|
|
7
|
+
code?: DomainVerificationErrorCode;
|
|
8
|
+
context?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Base domain verification error, following the Wave 2/3 standard shape:
|
|
12
|
+
* options-based constructor, ES2022 `cause`, typed `code`, `context` bag for
|
|
13
|
+
* legacy positional fields (e.g. `retryable`, `details`).
|
|
3
14
|
*/
|
|
4
15
|
export declare class DomainVerificationError extends Error {
|
|
5
|
-
code:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
constructor(message: string, code: string, retryable?: boolean, details?: unknown | undefined);
|
|
16
|
+
readonly code: DomainVerificationErrorCode;
|
|
17
|
+
readonly context?: Record<string, unknown>;
|
|
18
|
+
constructor(message: string, options?: DomainVerificationErrorOptions);
|
|
9
19
|
}
|
|
10
20
|
export declare class DNSPropagationError extends DomainVerificationError {
|
|
11
|
-
constructor(message: string,
|
|
21
|
+
constructor(message: string, options?: Omit<DomainVerificationErrorOptions, 'code'>);
|
|
12
22
|
}
|
|
13
23
|
export declare class ProviderAPIError extends DomainVerificationError {
|
|
14
|
-
constructor(message: string,
|
|
24
|
+
constructor(message: string, options?: Omit<DomainVerificationErrorOptions, 'code'>);
|
|
15
25
|
}
|
|
16
26
|
export declare class InvalidDomainError extends DomainVerificationError {
|
|
17
|
-
constructor(message: string,
|
|
27
|
+
constructor(message: string, options?: Omit<DomainVerificationErrorOptions, 'code'>);
|
|
18
28
|
}
|
|
19
29
|
/**
|
|
20
30
|
* Structured result pattern for all service operations
|
|
@@ -34,6 +44,7 @@ export interface ServiceResult<T = unknown> {
|
|
|
34
44
|
*/
|
|
35
45
|
export declare function successResult<T>(data: T): ServiceResult<T>;
|
|
36
46
|
/**
|
|
37
|
-
* Helper to create error result
|
|
47
|
+
* Helper to create error result. `retryable` and `details` are read from
|
|
48
|
+
* `error.context` (the standard location for legacy positional fields).
|
|
38
49
|
*/
|
|
39
50
|
export declare function errorResult(error: DomainVerificationError): ServiceResult;
|
package/dist/errors.js
CHANGED
|
@@ -11,35 +11,53 @@ exports.InvalidDomainError = exports.ProviderAPIError = exports.DNSPropagationEr
|
|
|
11
11
|
exports.successResult = successResult;
|
|
12
12
|
exports.errorResult = errorResult;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
14
|
+
* Base domain verification error, following the Wave 2/3 standard shape:
|
|
15
|
+
* options-based constructor, ES2022 `cause`, typed `code`, `context` bag for
|
|
16
|
+
* legacy positional fields (e.g. `retryable`, `details`).
|
|
15
17
|
*/
|
|
16
18
|
class DomainVerificationError extends Error {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
this.details = details;
|
|
19
|
+
code;
|
|
20
|
+
context;
|
|
21
|
+
constructor(message, options) {
|
|
22
|
+
super(message, options?.cause ? { cause: options.cause } : undefined);
|
|
22
23
|
this.name = 'DomainVerificationError';
|
|
24
|
+
this.code = options?.code ?? 'DOMAIN_VERIFICATION_ERROR';
|
|
25
|
+
if (options?.context !== undefined) {
|
|
26
|
+
this.context = options.context;
|
|
27
|
+
}
|
|
28
|
+
Error.captureStackTrace?.(this, this.constructor);
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
exports.DomainVerificationError = DomainVerificationError;
|
|
26
32
|
class DNSPropagationError extends DomainVerificationError {
|
|
27
|
-
constructor(message,
|
|
28
|
-
super(message,
|
|
33
|
+
constructor(message, options) {
|
|
34
|
+
super(message, {
|
|
35
|
+
...options,
|
|
36
|
+
code: 'DNS_PROPAGATION_ERROR',
|
|
37
|
+
context: { retryable: true, ...(options?.context ?? {}) }
|
|
38
|
+
});
|
|
29
39
|
this.name = 'DNSPropagationError';
|
|
30
40
|
}
|
|
31
41
|
}
|
|
32
42
|
exports.DNSPropagationError = DNSPropagationError;
|
|
33
43
|
class ProviderAPIError extends DomainVerificationError {
|
|
34
|
-
constructor(message,
|
|
35
|
-
super(message,
|
|
44
|
+
constructor(message, options) {
|
|
45
|
+
super(message, {
|
|
46
|
+
...options,
|
|
47
|
+
code: 'PROVIDER_API_ERROR',
|
|
48
|
+
context: { retryable: true, ...(options?.context ?? {}) }
|
|
49
|
+
});
|
|
36
50
|
this.name = 'ProviderAPIError';
|
|
37
51
|
}
|
|
38
52
|
}
|
|
39
53
|
exports.ProviderAPIError = ProviderAPIError;
|
|
40
54
|
class InvalidDomainError extends DomainVerificationError {
|
|
41
|
-
constructor(message,
|
|
42
|
-
super(message,
|
|
55
|
+
constructor(message, options) {
|
|
56
|
+
super(message, {
|
|
57
|
+
...options,
|
|
58
|
+
code: 'INVALID_DOMAIN',
|
|
59
|
+
context: { retryable: false, ...(options?.context ?? {}) }
|
|
60
|
+
});
|
|
43
61
|
this.name = 'InvalidDomainError';
|
|
44
62
|
}
|
|
45
63
|
}
|
|
@@ -51,16 +69,18 @@ function successResult(data) {
|
|
|
51
69
|
return { success: true, data };
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
|
-
* Helper to create error result
|
|
72
|
+
* Helper to create error result. `retryable` and `details` are read from
|
|
73
|
+
* `error.context` (the standard location for legacy positional fields).
|
|
55
74
|
*/
|
|
56
75
|
function errorResult(error) {
|
|
76
|
+
const ctx = error.context ?? {};
|
|
57
77
|
return {
|
|
58
78
|
success: false,
|
|
59
79
|
error: {
|
|
60
80
|
code: error.code,
|
|
61
81
|
message: error.message,
|
|
62
|
-
retryable:
|
|
63
|
-
details:
|
|
82
|
+
retryable: typeof ctx.retryable === 'boolean' ? ctx.retryable : false,
|
|
83
|
+
details: ctx.details
|
|
64
84
|
}
|
|
65
85
|
};
|
|
66
86
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bernierllc/email-domain-verification",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Programmatic domain setup and DNS management for production email sending with multi-provider support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/**/*",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
7
11
|
"keywords": [
|
|
8
12
|
"email",
|
|
9
13
|
"domain",
|
|
@@ -25,10 +29,10 @@
|
|
|
25
29
|
"cron": "^3.1.6",
|
|
26
30
|
"dns-packet": "^5.6.1",
|
|
27
31
|
"dns2": "^2.1.0",
|
|
28
|
-
"@bernierllc/crypto-utils": "1.
|
|
29
|
-
"@bernierllc/email-sender-manager": "1.
|
|
30
|
-
"@bernierllc/logger": "1.
|
|
31
|
-
"@bernierllc/neverhub-adapter": "0.
|
|
32
|
+
"@bernierllc/crypto-utils": "1.4.0",
|
|
33
|
+
"@bernierllc/email-sender-manager": "1.6.0",
|
|
34
|
+
"@bernierllc/logger": "1.7.0",
|
|
35
|
+
"@bernierllc/neverhub-adapter": "0.4.0"
|
|
32
36
|
},
|
|
33
37
|
"devDependencies": {
|
|
34
38
|
"@types/cron": "^2.0.1",
|
package/.eslintrc.cjs
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) 2025 Bernier LLC
|
|
3
|
-
|
|
4
|
-
This file is licensed to the client under a limited-use license.
|
|
5
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
module.exports = {
|
|
10
|
-
parser: '@typescript-eslint/parser',
|
|
11
|
-
extends: [
|
|
12
|
-
'eslint:recommended',
|
|
13
|
-
'plugin:@typescript-eslint/recommended',
|
|
14
|
-
],
|
|
15
|
-
parserOptions: {
|
|
16
|
-
ecmaVersion: 2020,
|
|
17
|
-
sourceType: 'module',
|
|
18
|
-
},
|
|
19
|
-
rules: {
|
|
20
|
-
'@typescript-eslint/no-explicit-any': 'warn',
|
|
21
|
-
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
22
|
-
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
23
|
-
},
|
|
24
|
-
env: {
|
|
25
|
-
node: true,
|
|
26
|
-
es6: true,
|
|
27
|
-
jest: true,
|
|
28
|
-
},
|
|
29
|
-
};
|
package/CHANGELOG.md
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
-
|
|
6
|
-
# 1.1.0 (2026-05-20)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### Features
|
|
10
|
-
|
|
11
|
-
* **contentful-types:** es2022, errors.ts with error.cause ([b74c636](https://github.com/bernierllc/tools/commit/b74c636e9c4675885c9386dcd413c5163a166ef8))
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## [1.0.12](https://github.com/bernierllc/tools/compare/@bernierllc/email-domain-verification@1.0.11...@bernierllc/email-domain-verification@1.0.12) (2026-05-19)
|
|
18
|
-
|
|
19
|
-
**Note:** Version bump only for package @bernierllc/email-domain-verification
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
## [1.0.11](https://github.com/bernierllc/tools/compare/@bernierllc/email-domain-verification@1.0.10...@bernierllc/email-domain-verification@1.0.11) (2026-05-19)
|
|
26
|
-
|
|
27
|
-
**Note:** Version bump only for package @bernierllc/email-domain-verification
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## [1.0.10](https://github.com/bernierllc/tools/compare/@bernierllc/email-domain-verification@1.0.9...@bernierllc/email-domain-verification@1.0.10) (2026-03-30)
|
|
34
|
-
|
|
35
|
-
**Note:** Version bump only for package @bernierllc/email-domain-verification
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
## [1.0.9](https://github.com/bernierllc/tools/compare/@bernierllc/email-domain-verification@1.0.8...@bernierllc/email-domain-verification@1.0.9) (2026-03-21)
|
|
42
|
-
|
|
43
|
-
**Note:** Version bump only for package @bernierllc/email-domain-verification
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
## [1.0.8](https://github.com/bernierllc/tools/compare/@bernierllc/email-domain-verification@1.0.7...@bernierllc/email-domain-verification@1.0.8) (2026-03-09)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
### Bug Fixes
|
|
53
|
-
|
|
54
|
-
* **email:** sync provider type unions across email packages ([b515e54](https://github.com/bernierllc/tools/commit/b515e5456da4ce6fd6067d20e4da010d658e3a2b))
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
## [1.0.7](https://github.com/bernierllc/tools/compare/@bernierllc/email-domain-verification@1.0.6...@bernierllc/email-domain-verification@1.0.7) (2026-03-03)
|
|
61
|
-
|
|
62
|
-
**Note:** Version bump only for package @bernierllc/email-domain-verification
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
## 1.0.6 (2025-12-25)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
### Bug Fixes
|
|
72
|
-
|
|
73
|
-
* **ci:** add lerna version step before publish ([3d20300](https://github.com/bernierllc/tools/commit/3d203002143bf353fffafe4f8a78a99009567347))
|
|
74
|
-
* **ci:** fix release workflow + convert internal deps to workspace:* ([01c078b](https://github.com/bernierllc/tools/commit/01c078b49d6025f7eef750f79207a1c71c8d85dc))
|
|
75
|
-
* update neverhub-adapter deps to workspace:* and publish 0.1.2 ([f0e3d04](https://github.com/bernierllc/tools/commit/f0e3d04d8d4f094e3bb899ddf81e93243d16e2c2))
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
## 1.0.5 (2025-12-25)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
### Bug Fixes
|
|
85
|
-
|
|
86
|
-
* **ci:** fix release workflow + convert internal deps to workspace:* ([01c078b](https://github.com/bernierllc/tools/commit/01c078b49d6025f7eef750f79207a1c71c8d85dc))
|
|
87
|
-
* update neverhub-adapter deps to workspace:* and publish 0.1.2 ([f0e3d04](https://github.com/bernierllc/tools/commit/f0e3d04d8d4f094e3bb899ddf81e93243d16e2c2))
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
# @bernierllc/email-domain-verification
|
|
94
|
-
|
|
95
|
-
## 1.0.4
|
|
96
|
-
|
|
97
|
-
### Patch Changes
|
|
98
|
-
|
|
99
|
-
- Updated dependencies [[`73c1d1e`](https://github.com/bernierllc/tools/commit/73c1d1e46114cf2ccfd5b74b83743361247f4502)]:
|
|
100
|
-
- @bernierllc/logger@1.1.0
|
|
101
|
-
|
|
102
|
-
## 1.0.3
|
|
103
|
-
|
|
104
|
-
### Patch Changes
|
|
105
|
-
|
|
106
|
-
- Updated dependencies [[`24899fa`](https://github.com/bernierllc/tools/commit/24899fa4eaf80ae329f7bd74483cf97a132f5d4c)]:
|
|
107
|
-
- @bernierllc/logger@1.0.4
|
|
108
|
-
|
|
109
|
-
## 1.0.2
|
|
110
|
-
|
|
111
|
-
### Patch Changes
|
|
112
|
-
|
|
113
|
-
- Updated dependencies [[`a314763`](https://github.com/bernierllc/tools/commit/a31476336717301e410da2b0b64c8f1ee44c0e8d)]:
|
|
114
|
-
- @bernierllc/crypto-utils@1.0.4
|
|
115
|
-
|
|
116
|
-
## 1.0.1
|
|
117
|
-
|
|
118
|
-
### Patch Changes
|
|
119
|
-
|
|
120
|
-
- Updated dependencies [[`a65f28c`](https://github.com/bernierllc/tools/commit/a65f28c2a1d09da8e8c7c23dcebd8f6606d9783f)]:
|
|
121
|
-
- @bernierllc/crypto-utils@1.0.3
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) 2025 Bernier LLC
|
|
3
|
-
|
|
4
|
-
This file is licensed to the client under a limited-use license.
|
|
5
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export async function generateUUIDKey(): Promise<{ key: string }> {
|
|
10
|
-
return { key: `test-uuid-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` };
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function generateSecureToken(length = 32): string {
|
|
14
|
-
return Array(length).fill(0).map(() => Math.random().toString(36).charAt(2)).join('');
|
|
15
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) 2025 Bernier LLC
|
|
3
|
-
|
|
4
|
-
This file is licensed to the client under a limited-use license.
|
|
5
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export enum LogLevel {
|
|
10
|
-
DEBUG = 0,
|
|
11
|
-
INFO = 1,
|
|
12
|
-
WARN = 2,
|
|
13
|
-
ERROR = 3,
|
|
14
|
-
FATAL = 4,
|
|
15
|
-
SILENT = 5
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface LoggerOptions {
|
|
19
|
-
level?: LogLevel;
|
|
20
|
-
transports?: unknown[];
|
|
21
|
-
context?: Record<string, unknown>;
|
|
22
|
-
enableCorrelation?: boolean;
|
|
23
|
-
sanitize?: boolean;
|
|
24
|
-
sanitizeFields?: string[];
|
|
25
|
-
onError?: (error: Error, transport: string) => void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class Logger {
|
|
29
|
-
constructor(_options: LoggerOptions) {}
|
|
30
|
-
|
|
31
|
-
debug(_message: string, _metadata?: Record<string, unknown>): void {}
|
|
32
|
-
info(_message: string, _metadata?: Record<string, unknown>): void {}
|
|
33
|
-
warn(_message: string, _metadata?: Record<string, unknown>): void {}
|
|
34
|
-
error(_message: string, _metadata?: Record<string, unknown>): void {}
|
|
35
|
-
fatal(_message: string, _metadata?: Record<string, unknown>): void {}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export class ConsoleTransport {
|
|
39
|
-
constructor(_options: { level?: LogLevel } = {}) {}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const createLogger = (options: LoggerOptions = { level: LogLevel.SILENT }) => new Logger(options);
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Copyright (c) 2025 Bernier LLC
|
|
3
|
-
|
|
4
|
-
This file is licensed to the client under a limited-use license.
|
|
5
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
6
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export class NeverHubAdapter {
|
|
10
|
-
static async detect(): Promise<boolean> {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async register(_config: Record<string, unknown>): Promise<void> {}
|
|
15
|
-
async publishEvent(_event: Record<string, unknown>): Promise<void> {}
|
|
16
|
-
async subscribe(_eventType: string, _handler: (event: unknown) => void): Promise<void> {}
|
|
17
|
-
}
|