@bernierllc/email-sendgrid-plugin 1.8.1 → 1.8.2
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/package.json +2 -2
- package/dist/api/errors.d.ts +0 -20
- package/dist/api/errors.js +0 -55
- package/dist/api/rate-limiter.d.ts +0 -17
- package/dist/api/rate-limiter.js +0 -60
- package/dist/api/sendgrid-client.d.ts +0 -21
- package/dist/api/sendgrid-client.js +0 -70
- package/dist/converters/sender-converter.d.ts +0 -30
- package/dist/converters/sender-converter.js +0 -114
- package/dist/converters/template-converter.d.ts +0 -11
- package/dist/converters/template-converter.js +0 -77
- package/dist/errors.d.ts +0 -11
- package/dist/errors.js +0 -24
- package/dist/index.d.ts +0 -15
- package/dist/index.js +0 -45
- package/dist/plugin/sender-manager.d.ts +0 -20
- package/dist/plugin/sender-manager.js +0 -129
- package/dist/plugin/sendgrid-plugin.d.ts +0 -60
- package/dist/plugin/sendgrid-plugin.js +0 -215
- package/dist/plugin/sync-manager.d.ts +0 -19
- package/dist/plugin/sync-manager.js +0 -98
- package/dist/plugin/template-manager.d.ts +0 -25
- package/dist/plugin/template-manager.js +0 -157
- package/dist/safety/ownership-validator.d.ts +0 -15
- package/dist/safety/ownership-validator.js +0 -44
- package/dist/safety/prefix-enforcer.d.ts +0 -8
- package/dist/safety/prefix-enforcer.js +0 -35
- package/dist/types/config-types.d.ts +0 -24
- package/dist/types/config-types.js +0 -9
- package/dist/types/plugin-types.d.ts +0 -79
- package/dist/types/plugin-types.js +0 -9
- package/dist/types/sendgrid-types.d.ts +0 -82
- package/dist/types/sendgrid-types.js +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bernierllc/email-sendgrid-plugin",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"deprecated": "This package is deprecated. SendGrid functionality has been merged into @bernierllc/email-sender@3.0.0+. See https://github.com/BernierLLC/tools/blob/main/packages/core/email-sender/MIGRATION.md for migration guide.",
|
|
5
5
|
"description": "SendGrid-specific template management, sender verification, and advanced features plugin for email template service",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"license": "SEE LICENSE IN LICENSE",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@sendgrid/mail": "^8.1.3",
|
|
24
|
-
"@bernierllc/logger": "
|
|
24
|
+
"@bernierllc/logger": "2.0.0",
|
|
25
25
|
"@bernierllc/rate-limiter": "0.7.0",
|
|
26
26
|
"@bernierllc/retry-policy": "0.7.0"
|
|
27
27
|
},
|
package/dist/api/errors.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare class SendGridApiError extends Error {
|
|
2
|
-
statusCode?: number | undefined;
|
|
3
|
-
response?: unknown | undefined;
|
|
4
|
-
constructor(message: string, statusCode?: number | undefined, response?: unknown | undefined);
|
|
5
|
-
}
|
|
6
|
-
export declare class TemplateNotFoundError extends Error {
|
|
7
|
-
templateId: string;
|
|
8
|
-
constructor(templateId: string);
|
|
9
|
-
}
|
|
10
|
-
export declare class UnauthorizedTemplateAccessError extends Error {
|
|
11
|
-
constructor(message: string);
|
|
12
|
-
}
|
|
13
|
-
export declare class TemplateConflictError extends Error {
|
|
14
|
-
templateId: string;
|
|
15
|
-
conflicts: string[];
|
|
16
|
-
constructor(templateId: string, conflicts: string[]);
|
|
17
|
-
}
|
|
18
|
-
export declare class RateLimitError extends Error {
|
|
19
|
-
constructor(message: string);
|
|
20
|
-
}
|
package/dist/api/errors.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (c) 2025 Bernier LLC
|
|
4
|
-
|
|
5
|
-
This file is licensed to the client under a limited-use license.
|
|
6
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.RateLimitError = exports.TemplateConflictError = exports.UnauthorizedTemplateAccessError = exports.TemplateNotFoundError = exports.SendGridApiError = void 0;
|
|
11
|
-
class SendGridApiError extends Error {
|
|
12
|
-
statusCode;
|
|
13
|
-
response;
|
|
14
|
-
constructor(message, statusCode, response) {
|
|
15
|
-
super(message);
|
|
16
|
-
this.statusCode = statusCode;
|
|
17
|
-
this.response = response;
|
|
18
|
-
this.name = 'SendGridApiError';
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
exports.SendGridApiError = SendGridApiError;
|
|
22
|
-
class TemplateNotFoundError extends Error {
|
|
23
|
-
templateId;
|
|
24
|
-
constructor(templateId) {
|
|
25
|
-
super(`Template not found: ${templateId}`);
|
|
26
|
-
this.templateId = templateId;
|
|
27
|
-
this.name = 'TemplateNotFoundError';
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.TemplateNotFoundError = TemplateNotFoundError;
|
|
31
|
-
class UnauthorizedTemplateAccessError extends Error {
|
|
32
|
-
constructor(message) {
|
|
33
|
-
super(message);
|
|
34
|
-
this.name = 'UnauthorizedTemplateAccessError';
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
exports.UnauthorizedTemplateAccessError = UnauthorizedTemplateAccessError;
|
|
38
|
-
class TemplateConflictError extends Error {
|
|
39
|
-
templateId;
|
|
40
|
-
conflicts;
|
|
41
|
-
constructor(templateId, conflicts) {
|
|
42
|
-
super(`Template conflicts detected: ${conflicts.join(', ')}`);
|
|
43
|
-
this.templateId = templateId;
|
|
44
|
-
this.conflicts = conflicts;
|
|
45
|
-
this.name = 'TemplateConflictError';
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
exports.TemplateConflictError = TemplateConflictError;
|
|
49
|
-
class RateLimitError extends Error {
|
|
50
|
-
constructor(message) {
|
|
51
|
-
super(message);
|
|
52
|
-
this.name = 'RateLimitError';
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
exports.RateLimitError = RateLimitError;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface RateLimiterConfig {
|
|
2
|
-
maxRequestsPerSecond: number;
|
|
3
|
-
maxRequestsPerMinute: number;
|
|
4
|
-
}
|
|
5
|
-
export declare class SimpleRateLimiter {
|
|
6
|
-
private requestTimestamps;
|
|
7
|
-
private readonly maxRequestsPerSecond;
|
|
8
|
-
private readonly maxRequestsPerMinute;
|
|
9
|
-
constructor(config: RateLimiterConfig);
|
|
10
|
-
acquire(): Promise<void>;
|
|
11
|
-
release(): void;
|
|
12
|
-
private sleep;
|
|
13
|
-
getRemainingCapacity(): {
|
|
14
|
-
perSecond: number;
|
|
15
|
-
perMinute: number;
|
|
16
|
-
};
|
|
17
|
-
}
|
package/dist/api/rate-limiter.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (c) 2025 Bernier LLC
|
|
4
|
-
|
|
5
|
-
This file is licensed to the client under a limited-use license.
|
|
6
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.SimpleRateLimiter = void 0;
|
|
11
|
-
const errors_1 = require("./errors");
|
|
12
|
-
class SimpleRateLimiter {
|
|
13
|
-
requestTimestamps = [];
|
|
14
|
-
maxRequestsPerSecond;
|
|
15
|
-
maxRequestsPerMinute;
|
|
16
|
-
constructor(config) {
|
|
17
|
-
this.maxRequestsPerSecond = config.maxRequestsPerSecond;
|
|
18
|
-
this.maxRequestsPerMinute = config.maxRequestsPerMinute;
|
|
19
|
-
}
|
|
20
|
-
async acquire() {
|
|
21
|
-
const now = Date.now();
|
|
22
|
-
// Clean up old timestamps
|
|
23
|
-
this.requestTimestamps = this.requestTimestamps.filter(timestamp => now - timestamp < 60000 // Keep last minute
|
|
24
|
-
);
|
|
25
|
-
// Check per-second limit
|
|
26
|
-
const lastSecond = this.requestTimestamps.filter(timestamp => now - timestamp < 1000);
|
|
27
|
-
if (lastSecond.length >= this.maxRequestsPerSecond) {
|
|
28
|
-
const waitTime = 1000 - (now - lastSecond[0]);
|
|
29
|
-
await this.sleep(waitTime);
|
|
30
|
-
return this.acquire();
|
|
31
|
-
}
|
|
32
|
-
// Check per-minute limit
|
|
33
|
-
if (this.requestTimestamps.length >= this.maxRequestsPerMinute) {
|
|
34
|
-
const waitTime = 60000 - (now - this.requestTimestamps[0]);
|
|
35
|
-
if (waitTime > 5000) {
|
|
36
|
-
throw new errors_1.RateLimitError(`Rate limit exceeded, would need to wait ${Math.ceil(waitTime / 1000)}s`);
|
|
37
|
-
}
|
|
38
|
-
await this.sleep(waitTime);
|
|
39
|
-
return this.acquire();
|
|
40
|
-
}
|
|
41
|
-
// Add timestamp and proceed
|
|
42
|
-
this.requestTimestamps.push(now);
|
|
43
|
-
}
|
|
44
|
-
release() {
|
|
45
|
-
// No-op for simple implementation
|
|
46
|
-
}
|
|
47
|
-
sleep(ms) {
|
|
48
|
-
return new Promise(resolve => setTimeout(resolve, Math.max(0, ms)));
|
|
49
|
-
}
|
|
50
|
-
getRemainingCapacity() {
|
|
51
|
-
const now = Date.now();
|
|
52
|
-
const lastSecond = this.requestTimestamps.filter(timestamp => now - timestamp < 1000).length;
|
|
53
|
-
const lastMinute = this.requestTimestamps.length;
|
|
54
|
-
return {
|
|
55
|
-
perSecond: Math.max(0, this.maxRequestsPerSecond - lastSecond),
|
|
56
|
-
perMinute: Math.max(0, this.maxRequestsPerMinute - lastMinute)
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
exports.SimpleRateLimiter = SimpleRateLimiter;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { ApiRequestOptions, ApiResponse } from '../types/config-types';
|
|
2
|
-
import { SimpleRateLimiter } from './rate-limiter';
|
|
3
|
-
export interface SendGridClientConfig {
|
|
4
|
-
apiKey: string;
|
|
5
|
-
rateLimiter?: SimpleRateLimiter;
|
|
6
|
-
logger?: {
|
|
7
|
-
debug: (message: string) => void;
|
|
8
|
-
error: (message: string) => void;
|
|
9
|
-
info: (message: string) => void;
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
export declare class SendGridClient {
|
|
13
|
-
private readonly apiKey;
|
|
14
|
-
private readonly rateLimiter?;
|
|
15
|
-
private readonly logger?;
|
|
16
|
-
private readonly baseUrl;
|
|
17
|
-
constructor(config: SendGridClientConfig);
|
|
18
|
-
request(endpoint: string, options: ApiRequestOptions): Promise<ApiResponse>;
|
|
19
|
-
isSuccessResponse(response: ApiResponse): boolean;
|
|
20
|
-
parseResponseBody<T>(response: ApiResponse): T;
|
|
21
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (c) 2025 Bernier LLC
|
|
4
|
-
|
|
5
|
-
This file is licensed to the client under a limited-use license.
|
|
6
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.SendGridClient = void 0;
|
|
11
|
-
const errors_1 = require("./errors");
|
|
12
|
-
class SendGridClient {
|
|
13
|
-
apiKey;
|
|
14
|
-
rateLimiter;
|
|
15
|
-
logger;
|
|
16
|
-
baseUrl = 'https://api.sendgrid.com/v3';
|
|
17
|
-
constructor(config) {
|
|
18
|
-
this.apiKey = config.apiKey;
|
|
19
|
-
this.rateLimiter = config.rateLimiter;
|
|
20
|
-
this.logger = config.logger;
|
|
21
|
-
}
|
|
22
|
-
async request(endpoint, options) {
|
|
23
|
-
// Apply rate limiting if configured
|
|
24
|
-
if (this.rateLimiter) {
|
|
25
|
-
await this.rateLimiter.acquire();
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
const url = `${this.baseUrl}${endpoint}`;
|
|
29
|
-
const response = await fetch(url, {
|
|
30
|
-
method: options.method,
|
|
31
|
-
headers: {
|
|
32
|
-
'Authorization': `Bearer ${this.apiKey}`,
|
|
33
|
-
'Content-Type': 'application/json',
|
|
34
|
-
...options.headers
|
|
35
|
-
},
|
|
36
|
-
body: options.body
|
|
37
|
-
});
|
|
38
|
-
const body = await response.text();
|
|
39
|
-
// Log all API calls for audit trail
|
|
40
|
-
this.logger?.debug(`SendGrid API ${options.method} ${endpoint}: ${response.status}`);
|
|
41
|
-
return {
|
|
42
|
-
statusCode: response.status,
|
|
43
|
-
headers: Object.fromEntries(response.headers.entries()),
|
|
44
|
-
body
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
49
|
-
this.logger?.error(`SendGrid API error: ${errorMessage}`);
|
|
50
|
-
throw new errors_1.SendGridApiError(`API request failed: ${errorMessage}`, undefined, error);
|
|
51
|
-
}
|
|
52
|
-
finally {
|
|
53
|
-
if (this.rateLimiter) {
|
|
54
|
-
this.rateLimiter.release();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
isSuccessResponse(response) {
|
|
59
|
-
return response.statusCode >= 200 && response.statusCode < 300;
|
|
60
|
-
}
|
|
61
|
-
parseResponseBody(response) {
|
|
62
|
-
try {
|
|
63
|
-
return JSON.parse(response.body);
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
throw new errors_1.SendGridApiError('Failed to parse response body', response.statusCode, response.body);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
exports.SendGridClient = SendGridClient;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { VerifiedSender, SendGridVerifiedSenderData, EmailAttachment, SendGridAttachment, SendGridMailPayload } from '../types/sendgrid-types';
|
|
2
|
-
export declare class SenderConverter {
|
|
3
|
-
convertToVerifiedSender(sendgridData: SendGridVerifiedSenderData): VerifiedSender;
|
|
4
|
-
/**
|
|
5
|
-
* Convert a single EmailAttachment to SendGrid's attachment format.
|
|
6
|
-
*/
|
|
7
|
-
convertAttachment(attachment: EmailAttachment): SendGridAttachment;
|
|
8
|
-
/**
|
|
9
|
-
* Convert an array of EmailAttachment objects to SendGrid format.
|
|
10
|
-
* Returns undefined if the array is empty or undefined (so the field
|
|
11
|
-
* can be omitted from the payload).
|
|
12
|
-
*/
|
|
13
|
-
convertAttachments(attachments?: EmailAttachment[]): SendGridAttachment[] | undefined;
|
|
14
|
-
/**
|
|
15
|
-
* Convert custom headers to the format expected by SendGrid's v3 mail send API.
|
|
16
|
-
* Filters out reserved SendGrid headers that must not be overridden.
|
|
17
|
-
* Returns undefined if no valid headers remain.
|
|
18
|
-
*/
|
|
19
|
-
convertHeaders(headers?: Record<string, string>): Record<string, string> | undefined;
|
|
20
|
-
/**
|
|
21
|
-
* Build the attachment and header portion of a SendGrid mail payload
|
|
22
|
-
* from canonical email data.
|
|
23
|
-
*/
|
|
24
|
-
buildMailPayload(options: {
|
|
25
|
-
attachments?: EmailAttachment[];
|
|
26
|
-
headers?: Record<string, string>;
|
|
27
|
-
}): SendGridMailPayload;
|
|
28
|
-
extractDomain(email: string): string;
|
|
29
|
-
isDomainMatch(domain1: string, domain2: string): boolean;
|
|
30
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (c) 2025 Bernier LLC
|
|
4
|
-
|
|
5
|
-
This file is licensed to the client under a limited-use license.
|
|
6
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.SenderConverter = void 0;
|
|
11
|
-
class SenderConverter {
|
|
12
|
-
convertToVerifiedSender(sendgridData) {
|
|
13
|
-
const domain = this.extractDomain(sendgridData.from_email);
|
|
14
|
-
return {
|
|
15
|
-
id: sendgridData.id.toString(),
|
|
16
|
-
email: sendgridData.from_email,
|
|
17
|
-
name: sendgridData.from_name || sendgridData.nickname,
|
|
18
|
-
isVerified: sendgridData.verified,
|
|
19
|
-
domain,
|
|
20
|
-
verificationStatus: sendgridData.verified ? 'verified' : 'pending',
|
|
21
|
-
createdAt: new Date(), // SendGrid doesn't provide creation date
|
|
22
|
-
lastVerifiedAt: sendgridData.verified ? new Date() : undefined
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Convert a single EmailAttachment to SendGrid's attachment format.
|
|
27
|
-
*/
|
|
28
|
-
convertAttachment(attachment) {
|
|
29
|
-
const sgAttachment = {
|
|
30
|
-
content: attachment.content,
|
|
31
|
-
filename: attachment.filename,
|
|
32
|
-
};
|
|
33
|
-
if (attachment.contentType) {
|
|
34
|
-
sgAttachment.type = attachment.contentType;
|
|
35
|
-
}
|
|
36
|
-
if (attachment.disposition) {
|
|
37
|
-
sgAttachment.disposition = attachment.disposition;
|
|
38
|
-
}
|
|
39
|
-
return sgAttachment;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Convert an array of EmailAttachment objects to SendGrid format.
|
|
43
|
-
* Returns undefined if the array is empty or undefined (so the field
|
|
44
|
-
* can be omitted from the payload).
|
|
45
|
-
*/
|
|
46
|
-
convertAttachments(attachments) {
|
|
47
|
-
if (!attachments || attachments.length === 0) {
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
|
-
return attachments.map(a => this.convertAttachment(a));
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Convert custom headers to the format expected by SendGrid's v3 mail send API.
|
|
54
|
-
* Filters out reserved SendGrid headers that must not be overridden.
|
|
55
|
-
* Returns undefined if no valid headers remain.
|
|
56
|
-
*/
|
|
57
|
-
convertHeaders(headers) {
|
|
58
|
-
if (!headers || Object.keys(headers).length === 0) {
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
61
|
-
const RESERVED_HEADERS = new Set([
|
|
62
|
-
'x-sg-id',
|
|
63
|
-
'x-sg-eid',
|
|
64
|
-
'received',
|
|
65
|
-
'dkim-signature',
|
|
66
|
-
'content-type',
|
|
67
|
-
'content-transfer-encoding',
|
|
68
|
-
'to',
|
|
69
|
-
'from',
|
|
70
|
-
'subject',
|
|
71
|
-
'reply-to',
|
|
72
|
-
'cc',
|
|
73
|
-
'bcc',
|
|
74
|
-
]);
|
|
75
|
-
const filtered = {};
|
|
76
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
77
|
-
if (!RESERVED_HEADERS.has(key.toLowerCase())) {
|
|
78
|
-
filtered[key] = value;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return Object.keys(filtered).length > 0 ? filtered : undefined;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Build the attachment and header portion of a SendGrid mail payload
|
|
85
|
-
* from canonical email data.
|
|
86
|
-
*/
|
|
87
|
-
buildMailPayload(options) {
|
|
88
|
-
const payload = {};
|
|
89
|
-
const attachments = this.convertAttachments(options.attachments);
|
|
90
|
-
if (attachments) {
|
|
91
|
-
payload.attachments = attachments;
|
|
92
|
-
}
|
|
93
|
-
const headers = this.convertHeaders(options.headers);
|
|
94
|
-
if (headers) {
|
|
95
|
-
payload.headers = headers;
|
|
96
|
-
}
|
|
97
|
-
return payload;
|
|
98
|
-
}
|
|
99
|
-
extractDomain(email) {
|
|
100
|
-
return email.split('@')[1]?.toLowerCase() || '';
|
|
101
|
-
}
|
|
102
|
-
isDomainMatch(domain1, domain2) {
|
|
103
|
-
// Exact match
|
|
104
|
-
if (domain1 === domain2)
|
|
105
|
-
return true;
|
|
106
|
-
// Subdomain match (e.g., app.example.com matches example.com)
|
|
107
|
-
if (domain1.endsWith(`.${domain2}`))
|
|
108
|
-
return true;
|
|
109
|
-
if (domain2.endsWith(`.${domain1}`))
|
|
110
|
-
return true;
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
exports.SenderConverter = SenderConverter;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { SendGridTemplateData, SendGridTemplateVersion } from '../types/sendgrid-types';
|
|
2
|
-
import { ProviderTemplate, Template } from '../types/plugin-types';
|
|
3
|
-
import { PrefixEnforcer } from '../safety/prefix-enforcer';
|
|
4
|
-
export declare class TemplateConverter {
|
|
5
|
-
private readonly prefixEnforcer;
|
|
6
|
-
constructor(prefixEnforcer: PrefixEnforcer);
|
|
7
|
-
convertToProviderTemplate(sendgridData: SendGridTemplateData, activeVersion?: SendGridTemplateVersion): ProviderTemplate;
|
|
8
|
-
convertToLocalTemplate(sendgridData: SendGridTemplateData, localId: string, activeVersion?: SendGridTemplateVersion): Template;
|
|
9
|
-
extractVariables(content: string): string[];
|
|
10
|
-
private findActiveVersion;
|
|
11
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (c) 2025 Bernier LLC
|
|
4
|
-
|
|
5
|
-
This file is licensed to the client under a limited-use license.
|
|
6
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.TemplateConverter = void 0;
|
|
11
|
-
class TemplateConverter {
|
|
12
|
-
prefixEnforcer;
|
|
13
|
-
constructor(prefixEnforcer) {
|
|
14
|
-
this.prefixEnforcer = prefixEnforcer;
|
|
15
|
-
}
|
|
16
|
-
convertToProviderTemplate(sendgridData, activeVersion) {
|
|
17
|
-
// Find active version if not provided
|
|
18
|
-
const version = activeVersion || this.findActiveVersion(sendgridData.versions || []);
|
|
19
|
-
return {
|
|
20
|
-
id: sendgridData.id,
|
|
21
|
-
name: this.prefixEnforcer.stripPrefix(sendgridData.name),
|
|
22
|
-
subject: version?.subject || '',
|
|
23
|
-
htmlContent: version?.html_content || '',
|
|
24
|
-
textContent: version?.plain_content,
|
|
25
|
-
version: version?.name || '1.0.0',
|
|
26
|
-
active: version?.active === 1,
|
|
27
|
-
createdAt: new Date(sendgridData.updated_at),
|
|
28
|
-
updatedAt: new Date(sendgridData.updated_at)
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
convertToLocalTemplate(sendgridData, localId, activeVersion) {
|
|
32
|
-
const providerTemplate = this.convertToProviderTemplate(sendgridData, activeVersion);
|
|
33
|
-
return {
|
|
34
|
-
id: localId,
|
|
35
|
-
name: providerTemplate.name,
|
|
36
|
-
subject: providerTemplate.subject,
|
|
37
|
-
htmlContent: providerTemplate.htmlContent,
|
|
38
|
-
textContent: providerTemplate.textContent,
|
|
39
|
-
category: 'synced',
|
|
40
|
-
tags: ['sendgrid', 'synced'],
|
|
41
|
-
version: providerTemplate.version,
|
|
42
|
-
isActive: providerTemplate.active,
|
|
43
|
-
requiredVariables: [],
|
|
44
|
-
providerTemplateIds: {
|
|
45
|
-
sendgrid: sendgridData.id
|
|
46
|
-
},
|
|
47
|
-
lastSyncedAt: {
|
|
48
|
-
sendgrid: new Date()
|
|
49
|
-
},
|
|
50
|
-
syncStatus: {
|
|
51
|
-
sendgrid: 'success'
|
|
52
|
-
},
|
|
53
|
-
createdAt: providerTemplate.createdAt,
|
|
54
|
-
updatedAt: providerTemplate.updatedAt,
|
|
55
|
-
createdBy: 'sendgrid-sync',
|
|
56
|
-
lastModifiedBy: 'sendgrid-sync'
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
extractVariables(content) {
|
|
60
|
-
// Extract Handlebars-style variables: {{variableName}}
|
|
61
|
-
const regex = /\{\{([^}]+)\}\}/g;
|
|
62
|
-
const matches = content.matchAll(regex);
|
|
63
|
-
const variables = new Set();
|
|
64
|
-
for (const match of matches) {
|
|
65
|
-
const variable = match[1].trim();
|
|
66
|
-
// Filter out Handlebars helpers
|
|
67
|
-
if (!variable.startsWith('#') && !variable.startsWith('/')) {
|
|
68
|
-
variables.add(variable);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return Array.from(variables);
|
|
72
|
-
}
|
|
73
|
-
findActiveVersion(versions) {
|
|
74
|
-
return versions.find(v => v.active === 1) || versions[0];
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.TemplateConverter = TemplateConverter;
|
package/dist/errors.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export type EmailSendgridPluginErrorCode = 'EMAIL_SENDGRID_PLUGIN_ERROR' | 'INVALID_INPUT' | 'OPERATION_FAILED';
|
|
2
|
-
export interface EmailSendgridPluginErrorOptions {
|
|
3
|
-
cause?: Error;
|
|
4
|
-
code?: EmailSendgridPluginErrorCode;
|
|
5
|
-
context?: Record<string, unknown>;
|
|
6
|
-
}
|
|
7
|
-
export declare class EmailSendgridPluginError extends Error {
|
|
8
|
-
readonly code: EmailSendgridPluginErrorCode;
|
|
9
|
-
readonly context?: Record<string, unknown>;
|
|
10
|
-
constructor(message: string, options?: EmailSendgridPluginErrorOptions);
|
|
11
|
-
}
|
package/dist/errors.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (c) 2025 Bernier LLC
|
|
4
|
-
|
|
5
|
-
This file is licensed to the client under a limited-use license.
|
|
6
|
-
The client may use and modify this code only within the scope of the project it was delivered for.
|
|
7
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.EmailSendgridPluginError = void 0;
|
|
11
|
-
class EmailSendgridPluginError extends Error {
|
|
12
|
-
code;
|
|
13
|
-
context;
|
|
14
|
-
constructor(message, options) {
|
|
15
|
-
super(message, options?.cause ? { cause: options.cause } : undefined);
|
|
16
|
-
this.name = 'EmailSendgridPluginError';
|
|
17
|
-
this.code = options?.code ?? 'EMAIL_SENDGRID_PLUGIN_ERROR';
|
|
18
|
-
if (options?.context !== undefined) {
|
|
19
|
-
this.context = options.context;
|
|
20
|
-
}
|
|
21
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.EmailSendgridPluginError = EmailSendgridPluginError;
|
package/dist/index.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export { SendGridTemplatePlugin, TemplateProviderPlugin } from './plugin/sendgrid-plugin';
|
|
2
|
-
export { TemplateManager } from './plugin/template-manager';
|
|
3
|
-
export { SenderManager } from './plugin/sender-manager';
|
|
4
|
-
export { SyncManager } from './plugin/sync-manager';
|
|
5
|
-
export { SendGridClient } from './api/sendgrid-client';
|
|
6
|
-
export { SimpleRateLimiter } from './api/rate-limiter';
|
|
7
|
-
export { OwnershipValidator, SafetyMode } from './safety/ownership-validator';
|
|
8
|
-
export { PrefixEnforcer } from './safety/prefix-enforcer';
|
|
9
|
-
export { TemplateConverter } from './converters/template-converter';
|
|
10
|
-
export { SenderConverter } from './converters/sender-converter';
|
|
11
|
-
export { SendGridApiError, TemplateNotFoundError, UnauthorizedTemplateAccessError, TemplateConflictError, RateLimitError } from './api/errors';
|
|
12
|
-
export type { SendGridPluginConfig, ApiRequestOptions, ApiResponse } from './types/config-types';
|
|
13
|
-
export type { PluginConfig, ProviderCapability, Template, ProviderTemplate, TemplateVersion, SyncResult, ValidationResult, DateRange, TemplateAnalytics, FeatureConfig } from './types/plugin-types';
|
|
14
|
-
export type { VerifiedSender, SenderValidationResult, SendGridTemplateData, SendGridTemplateVersion, SendGridVerifiedSenderData, EmailAttachment, SendGridAttachment, SendGridMailPayload } from './types/sendgrid-types';
|
|
15
|
-
export { EmailSendgridPluginError, type EmailSendgridPluginErrorCode, type EmailSendgridPluginErrorOptions } from './errors';
|
package/dist/index.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
Copyright (c) 2025 Bernier LLC
|
|
4
|
-
|
|
5
|
-
This file is licensed to the client under a limited-use license.
|
|
6
|
-
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
-
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.EmailSendgridPluginError = exports.RateLimitError = exports.TemplateConflictError = exports.UnauthorizedTemplateAccessError = exports.TemplateNotFoundError = exports.SendGridApiError = exports.SenderConverter = exports.TemplateConverter = exports.PrefixEnforcer = exports.OwnershipValidator = exports.SimpleRateLimiter = exports.SendGridClient = exports.SyncManager = exports.SenderManager = exports.TemplateManager = exports.SendGridTemplatePlugin = void 0;
|
|
11
|
-
// Main plugin class
|
|
12
|
-
var sendgrid_plugin_1 = require("./plugin/sendgrid-plugin");
|
|
13
|
-
Object.defineProperty(exports, "SendGridTemplatePlugin", { enumerable: true, get: function () { return sendgrid_plugin_1.SendGridTemplatePlugin; } });
|
|
14
|
-
// Plugin components
|
|
15
|
-
var template_manager_1 = require("./plugin/template-manager");
|
|
16
|
-
Object.defineProperty(exports, "TemplateManager", { enumerable: true, get: function () { return template_manager_1.TemplateManager; } });
|
|
17
|
-
var sender_manager_1 = require("./plugin/sender-manager");
|
|
18
|
-
Object.defineProperty(exports, "SenderManager", { enumerable: true, get: function () { return sender_manager_1.SenderManager; } });
|
|
19
|
-
var sync_manager_1 = require("./plugin/sync-manager");
|
|
20
|
-
Object.defineProperty(exports, "SyncManager", { enumerable: true, get: function () { return sync_manager_1.SyncManager; } });
|
|
21
|
-
// API components
|
|
22
|
-
var sendgrid_client_1 = require("./api/sendgrid-client");
|
|
23
|
-
Object.defineProperty(exports, "SendGridClient", { enumerable: true, get: function () { return sendgrid_client_1.SendGridClient; } });
|
|
24
|
-
var rate_limiter_1 = require("./api/rate-limiter");
|
|
25
|
-
Object.defineProperty(exports, "SimpleRateLimiter", { enumerable: true, get: function () { return rate_limiter_1.SimpleRateLimiter; } });
|
|
26
|
-
// Safety components
|
|
27
|
-
var ownership_validator_1 = require("./safety/ownership-validator");
|
|
28
|
-
Object.defineProperty(exports, "OwnershipValidator", { enumerable: true, get: function () { return ownership_validator_1.OwnershipValidator; } });
|
|
29
|
-
var prefix_enforcer_1 = require("./safety/prefix-enforcer");
|
|
30
|
-
Object.defineProperty(exports, "PrefixEnforcer", { enumerable: true, get: function () { return prefix_enforcer_1.PrefixEnforcer; } });
|
|
31
|
-
// Converters
|
|
32
|
-
var template_converter_1 = require("./converters/template-converter");
|
|
33
|
-
Object.defineProperty(exports, "TemplateConverter", { enumerable: true, get: function () { return template_converter_1.TemplateConverter; } });
|
|
34
|
-
var sender_converter_1 = require("./converters/sender-converter");
|
|
35
|
-
Object.defineProperty(exports, "SenderConverter", { enumerable: true, get: function () { return sender_converter_1.SenderConverter; } });
|
|
36
|
-
// Errors
|
|
37
|
-
var errors_1 = require("./api/errors");
|
|
38
|
-
Object.defineProperty(exports, "SendGridApiError", { enumerable: true, get: function () { return errors_1.SendGridApiError; } });
|
|
39
|
-
Object.defineProperty(exports, "TemplateNotFoundError", { enumerable: true, get: function () { return errors_1.TemplateNotFoundError; } });
|
|
40
|
-
Object.defineProperty(exports, "UnauthorizedTemplateAccessError", { enumerable: true, get: function () { return errors_1.UnauthorizedTemplateAccessError; } });
|
|
41
|
-
Object.defineProperty(exports, "TemplateConflictError", { enumerable: true, get: function () { return errors_1.TemplateConflictError; } });
|
|
42
|
-
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_1.RateLimitError; } });
|
|
43
|
-
// Standard error type
|
|
44
|
-
var errors_2 = require("./errors");
|
|
45
|
-
Object.defineProperty(exports, "EmailSendgridPluginError", { enumerable: true, get: function () { return errors_2.EmailSendgridPluginError; } });
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { SendGridClient } from '../api/sendgrid-client';
|
|
2
|
-
import { SenderConverter } from '../converters/sender-converter';
|
|
3
|
-
import { VerifiedSender, SenderValidationResult } from '../types/sendgrid-types';
|
|
4
|
-
export declare class SenderManager {
|
|
5
|
-
private readonly client;
|
|
6
|
-
private readonly converter;
|
|
7
|
-
private readonly logger?;
|
|
8
|
-
private sendersCache?;
|
|
9
|
-
private cacheTimestamp?;
|
|
10
|
-
private readonly cacheTTL;
|
|
11
|
-
constructor(client: SendGridClient, converter: SenderConverter, logger?: {
|
|
12
|
-
info: (message: string) => void;
|
|
13
|
-
debug: (message: string) => void;
|
|
14
|
-
} | undefined);
|
|
15
|
-
getVerifiedSenders(useCache?: boolean): Promise<VerifiedSender[]>;
|
|
16
|
-
validateSender(email: string): Promise<SenderValidationResult>;
|
|
17
|
-
selectBestSender(fromEmail: string): Promise<VerifiedSender | null>;
|
|
18
|
-
clearCache(): void;
|
|
19
|
-
private getSenderSuggestions;
|
|
20
|
-
}
|