dymo-api 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/cjs/branches/private/functions/extractWithTextly/index.cjs +33 -0
  2. package/dist/cjs/branches/private/functions/getRandom/index.cjs +37 -0
  3. package/dist/cjs/branches/private/functions/isValidData/index.cjs +33 -0
  4. package/dist/cjs/branches/private/functions/isValidEmail/index.cjs +82 -0
  5. package/dist/cjs/branches/private/functions/protectReq/index.cjs +74 -0
  6. package/dist/cjs/branches/private/functions/protectReq/requestHandler.cjs +22 -0
  7. package/dist/cjs/branches/private/functions/sendEmail/index.cjs +88 -0
  8. package/dist/cjs/branches/private/index.cjs +22 -0
  9. package/dist/cjs/branches/public/functions/getPrayerTimes/index.cjs +31 -0
  10. package/dist/cjs/branches/public/functions/isValidPwd/index.cjs +65 -0
  11. package/dist/cjs/branches/public/functions/satinize/index.cjs +26 -0
  12. package/dist/cjs/branches/public/index.cjs +19 -0
  13. package/dist/cjs/config/index.cjs +0 -21
  14. package/dist/cjs/dymo-api.cjs +68 -16
  15. package/dist/cjs/lib/types/interfaces.cjs +2 -1
  16. package/dist/cjs/lib/types/well-known-bots.cjs +739 -0
  17. package/dist/cjs/utils/basics.cjs +18 -0
  18. package/dist/esm/branches/private/functions/extractWithTextly/index.js +29 -0
  19. package/dist/esm/branches/private/functions/getRandom/index.js +33 -0
  20. package/dist/esm/branches/private/functions/isValidData/index.js +29 -0
  21. package/dist/esm/branches/private/functions/isValidEmail/index.js +78 -0
  22. package/dist/esm/branches/private/functions/protectReq/index.js +37 -0
  23. package/dist/esm/branches/private/functions/protectReq/requestHandler.js +18 -0
  24. package/dist/esm/branches/private/functions/sendEmail/index.js +81 -0
  25. package/dist/esm/branches/private/index.js +6 -0
  26. package/dist/esm/branches/public/functions/getPrayerTimes/index.js +27 -0
  27. package/dist/esm/branches/{public.js → public/functions/isValidPwd/index.js} +28 -30
  28. package/dist/esm/branches/public/functions/satinize/index.js +22 -0
  29. package/dist/esm/branches/public/index.js +3 -0
  30. package/dist/esm/config/index.js +0 -15
  31. package/dist/esm/dymo-api.js +65 -16
  32. package/dist/esm/lib/types/interfaces.js +2 -1
  33. package/dist/esm/lib/types/well-known-bots.js +736 -0
  34. package/dist/esm/utils/basics.js +10 -0
  35. package/dist/types/branches/private/functions/extractWithTextly/index.d.ts +16 -0
  36. package/dist/types/branches/private/functions/getRandom/index.d.ts +16 -0
  37. package/dist/types/branches/private/functions/isValidData/index.d.ts +15 -0
  38. package/dist/types/branches/private/functions/isValidEmail/index.d.ts +20 -0
  39. package/dist/types/branches/private/functions/protectReq/index.d.ts +3 -0
  40. package/dist/types/branches/private/functions/protectReq/requestHandler.d.ts +22 -0
  41. package/dist/types/branches/private/functions/sendEmail/index.d.ts +18 -0
  42. package/dist/types/branches/private/index.d.ts +6 -0
  43. package/dist/types/branches/public/functions/getPrayerTimes/index.d.ts +17 -0
  44. package/dist/types/branches/public/functions/isValidPwd/index.d.ts +28 -0
  45. package/dist/types/branches/public/functions/satinize/index.d.ts +12 -0
  46. package/dist/types/branches/public/index.d.ts +3 -0
  47. package/dist/types/config/index.d.ts +0 -4
  48. package/dist/types/dymo-api.d.ts +38 -3
  49. package/dist/types/lib/types/interfaces.d.ts +2 -3
  50. package/dist/types/lib/types/primitives.d.ts +7 -0
  51. package/dist/types/lib/types/rules.d.ts +12 -0
  52. package/dist/types/lib/types/well-known-bots.d.ts +4 -0
  53. package/dist/types/utils/basics.d.ts +2 -0
  54. package/package.json +13 -5
  55. package/dist/cjs/branches/private.cjs +0 -284
  56. package/dist/cjs/branches/public.cjs +0 -102
  57. package/dist/esm/branches/private.js +0 -240
  58. package/dist/types/branches/private.d.ts +0 -76
  59. package/dist/types/branches/public.d.ts +0 -4
@@ -1,284 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.extractWithTextly = exports.getRandom = exports.sendEmail = exports.isValidEmail = exports.isValidData = void 0;
40
- const path_1 = __importDefault(require("path"));
41
- const react_1 = __importDefault(require("react"));
42
- const promises_1 = __importDefault(require("fs/promises"));
43
- const tw_to_css_1 = require("tw-to-css");
44
- const render_1 = require("@react-email/render");
45
- const config_1 = __importStar(require("../config/index.cjs"));
46
- const customError = (code, message) => {
47
- return Object.assign(new Error(), { code, message: `[${config_1.default.lib.name}] ${message}` });
48
- };
49
- const convertTailwindToInlineCss = (htmlContent) => {
50
- return htmlContent.replace(/class="([^"]+)"( style="([^"]+)")?/g, (match, classList, _, existingStyle) => {
51
- const compiledStyles = (0, tw_to_css_1.twi)(classList, { minify: true, merge: true });
52
- return match.replace(/class="[^"]+"/, "").replace(/ style="[^"]+"/, "").concat(` style="${existingStyle ? `${existingStyle.trim().slice(0, -1)}; ${compiledStyles}` : compiledStyles}"`);
53
- });
54
- };
55
- /**
56
- * Validates the provided data using a secure verification endpoint.
57
- *
58
- * @param token - A string or null representing the authentication token. Must not be null.
59
- * @param data - An object adhering to the Validator interface, containing at least one of the following fields:
60
- * url, email, phone, domain, creditCard, ip, wallet or user agent.
61
- *
62
- * @returns A promise that resolves to the response data from the verification endpoint.
63
- *
64
- * @throws Will throw an error if the token is null, if none of the required fields are present in the data,
65
- * or if an error occurs during the verification request.
66
- */
67
- const isValidData = async (token, data) => {
68
- if (token === null)
69
- throw customError(3000, "Invalid private token.");
70
- if (!Object.keys(data).some((key) => ["url", "email", "phone", "domain", "creditCard", "ip", "wallet", "userAgent"].includes(key) && data.hasOwnProperty(key)))
71
- throw customError(1500, "You must provide at least one parameter.");
72
- try {
73
- const response = await config_1.axiosApiUrl.post("/private/secure/verify", data, { headers: { "Content-Type": "application/json", "Authorization": token } });
74
- return response.data;
75
- }
76
- catch (error) {
77
- const statusCode = error.response?.status || 500;
78
- const errorMessage = error.response?.data?.message || error.message;
79
- const errorDetails = JSON.stringify(error.response?.data || {});
80
- throw customError(5000, `Error ${statusCode}: ${errorMessage}. Details: ${errorDetails}`);
81
- }
82
- };
83
- exports.isValidData = isValidData;
84
- /**
85
- * Validates an email using a secure verification endpoint.
86
- *
87
- * @param {string | null} token - Authentication token (required).
88
- * @param {Interfaces.EmailValidator} email - Email to validate.
89
- * @param {Interfaces.EmailValidatorRules} [rules] - Deny rules. Defaults to ["FRAUD", "INVALID", "NO_MX_RECORDS", "NO_REPLY_EMAIL"].
90
- *
91
- * Deny rules (some are premium ⚠️):
92
- * - "FRAUD", "INVALID", "NO_MX_RECORDS" ⚠️, "PROXIED_EMAIL" ⚠️, "FREE_SUBDOMAIN" ⚠️,
93
- * "PERSONAL_EMAIL", "CORPORATE_EMAIL", "NO_REPLY_EMAIL", "ROLE_ACCOUNT", "NO_REACHABLE", "HIGH_RISK_SCORE" ⚠️
94
- *
95
- * @returns {Promise<boolean>} True if the email passes all deny rules, false otherwise.
96
- * @throws Error if token is null, rules are empty, or request fails.
97
- *
98
- * @example
99
- * const valid = await isValidEmail(apiToken, "user@example.com", { deny: ["FRAUD", "NO_MX_RECORDS"] });
100
- */
101
- const isValidEmail = async (token, email, rules) => {
102
- if (token === null)
103
- throw customError(3000, "Invalid private token.");
104
- if (rules.deny.length === 0)
105
- throw customError(1500, "You must provide at least one deny rule.");
106
- try {
107
- const responseEmail = (await config_1.axiosApiUrl.post("/private/secure/verify", {
108
- email,
109
- plugins: [
110
- rules.deny.includes("NO_MX_RECORDS") ? "mxRecords" : undefined,
111
- rules.deny.includes("NO_REACHABLE") ? "reachability" : undefined,
112
- rules.deny.includes("HIGH_RISK_SCORE") ? "riskScore" : undefined
113
- ]
114
- }, { headers: { "Content-Type": "application/json", "Authorization": token } })).data.email;
115
- let reasons = [];
116
- if (rules.deny.includes("INVALID") && !responseEmail.valid)
117
- reasons.push("INVALID");
118
- if (rules.deny.includes("FRAUD") && responseEmail.fraud)
119
- reasons.push("FRAUD");
120
- if (rules.deny.includes("PROXIED_EMAIL") && responseEmail.proxiedEmail)
121
- reasons.push("PROXIED_EMAIL");
122
- if (rules.deny.includes("FREE_SUBDOMAIN") && responseEmail.freeSubdomain)
123
- reasons.push("FREE_SUBDOMAIN");
124
- if (rules.deny.includes("PERSONAL_EMAIL") && !responseEmail.corporate)
125
- reasons.push("PERSONAL_EMAIL");
126
- if (rules.deny.includes("CORPORATE_EMAIL") && responseEmail.corporate)
127
- reasons.push("CORPORATE_EMAIL");
128
- if (rules.deny.includes("NO_MX_RECORDS") && responseEmail.plugins.mxRecords.length === 0)
129
- reasons.push("NO_MX_RECORDS");
130
- if (rules.deny.includes("NO_REPLY_EMAIL") && responseEmail.noReply)
131
- reasons.push("NO_REPLY_EMAIL");
132
- if (rules.deny.includes("ROLE_ACCOUNT") && responseEmail.plugins.roleAccount)
133
- reasons.push("ROLE_ACCOUNT");
134
- if (rules.deny.includes("NO_REACHABLE") && !responseEmail.plugins.reachable)
135
- reasons.push("NO_REACHABLE");
136
- if (rules.deny.includes("HIGH_RISK_SCORE") && responseEmail.plugins.riskScore >= 80)
137
- reasons.push("HIGH_RISK_SCORE");
138
- return {
139
- email: responseEmail.email,
140
- allow: reasons.length === 0,
141
- reasons,
142
- response: responseEmail
143
- };
144
- }
145
- catch (error) {
146
- const statusCode = error.response?.status || 500;
147
- const errorMessage = error.response?.data?.message || error.message;
148
- const errorDetails = JSON.stringify(error.response?.data || {});
149
- throw customError(5000, `Error ${statusCode}: ${errorMessage}. Details: ${errorDetails}`);
150
- }
151
- };
152
- exports.isValidEmail = isValidEmail;
153
- /**
154
- * Sends an email using a secure sending endpoint.
155
- *
156
- * @param token - A string or null representing the authentication token. Must not be null.
157
- * @param data - An object adhering to the SendEmail interface, containing the following fields:
158
- * 'from', 'to', 'subject', 'html' or 'react', and optionally 'attachments', 'options', 'priority', 'waitToResponse', and 'composeTailwindClasses'.
159
- *
160
- * @returns A promise that resolves to the response data from the sending endpoint.
161
- *
162
- * @throws Will throw an error if the token is null, if any of the required fields are missing,
163
- * if the 'react' field is not a valid React element, if the 'attachments' field exceeds the maximum allowed size of 40 MB,
164
- * or if an error occurs during the sending request.
165
- */
166
- const sendEmail = async (token, data) => {
167
- if (token === null)
168
- throw customError(3000, "Invalid private token.");
169
- if (!data.from)
170
- throw customError(1500, "You must provide an email address from which the following will be sent.");
171
- if (!data.to)
172
- throw customError(1500, "You must provide an email to be sent to.");
173
- if (!data.subject)
174
- throw customError(1500, "You must provide a subject for the email to be sent.");
175
- if (!data.html && !data.react && !react_1.default.isValidElement(data.react))
176
- throw customError(1500, "You must provide HTML or a React component.");
177
- if (data.html && data.react)
178
- throw customError(1500, "You must provide only HTML or a React component, not both.");
179
- try {
180
- if (data.react) {
181
- //@ts-ignore
182
- data.html = await (0, render_1.render)(data.react);
183
- delete data.react;
184
- }
185
- if (data.options && data.options.composeTailwindClasses) {
186
- data.html = convertTailwindToInlineCss(data.html);
187
- delete data.options.composeTailwindClasses;
188
- }
189
- }
190
- catch (error) {
191
- throw customError(1500, `An error occurred while rendering your React component. Details: ${error}`);
192
- }
193
- try {
194
- let totalSize = 0;
195
- if (data.attachments && Array.isArray(data.attachments)) {
196
- const processedAttachments = await Promise.all(data.attachments.map(async (attachment) => {
197
- if ((attachment.path && attachment.content) || (!attachment.path && !attachment.content))
198
- throw customError(1500, "You must provide either 'path' or 'content', not both.");
199
- let contentBuffer;
200
- if (attachment.path)
201
- contentBuffer = await promises_1.default.readFile(path_1.default.resolve(attachment.path));
202
- else if (attachment.content)
203
- contentBuffer = attachment.content instanceof Buffer ? attachment.content : Buffer.from(attachment.content);
204
- totalSize += Buffer.byteLength(contentBuffer);
205
- if (totalSize > 40 * 1024 * 1024)
206
- throw customError(1500, "Attachments exceed the maximum allowed size of 40 MB.");
207
- return {
208
- filename: attachment.filename || path_1.default.basename(attachment.path || ""),
209
- content: contentBuffer,
210
- cid: attachment.cid || attachment.filename
211
- };
212
- }));
213
- data.attachments = processedAttachments;
214
- }
215
- const response = await config_1.axiosApiUrl.post("/private/sender/sendEmail", data, { headers: { "Authorization": token } });
216
- return response.data;
217
- }
218
- catch (error) {
219
- throw customError(5000, error.response?.data?.message || error.message);
220
- }
221
- };
222
- exports.sendEmail = sendEmail;
223
- /**
224
- * Retrieves a random number within a specified range using a secure endpoint.
225
- *
226
- * @param token - A string or null representing the authentication token. Must not be null.
227
- * @param data - An object adhering to the SRNG interface, containing 'min' and 'max' fields,
228
- * which define the inclusive range within which the random number should be generated.
229
- *
230
- * @returns A promise that resolves to the response data containing the random number.
231
- *
232
- * @throws Will throw an error if the token is null, if 'min' or 'max' are not defined,
233
- * if 'min' is not less than 'max', if 'min' or 'max' are out of the allowed range,
234
- * or if an error occurs during the request to the random number generator endpoint.
235
- */
236
- const getRandom = async (token, data) => {
237
- if (token === null)
238
- throw customError(3000, "Invalid private token.");
239
- if (!data.min || !data.max)
240
- throw customError(1500, "Both 'min' and 'max' parameters must be defined.");
241
- if (data.min >= data.max)
242
- throw customError(1500, "'min' must be less than 'max'.");
243
- if (data.min < -1000000000 || data.min > 1000000000)
244
- throw customError(1500, "'min' must be an integer in the interval [-1000000000}, 1000000000].");
245
- if (data.max < -1000000000 || data.max > 1000000000)
246
- throw customError(1500, "'max' must be an integer in the interval [-1000000000}, 1000000000].");
247
- try {
248
- const response = await config_1.axiosApiUrl.post("/private/srng", data, { headers: { "Content-Type": "application/json", "Authorization": token } });
249
- return response.data;
250
- }
251
- catch (error) {
252
- throw customError(5000, error.response?.data?.message || error.message);
253
- }
254
- };
255
- exports.getRandom = getRandom;
256
- /**
257
- * Extracts structured data from a given string using a secure endpoint.
258
- *
259
- * @param token - A string or null representing the authentication token. Must not be null.
260
- * @param data - An object adhering to the ExtractWithTextly interface, containing 'data' and 'format' fields.
261
- * The 'data' field is the string from which structured data should be extracted.
262
- * The 'format' field is an object defining the structure of the data to be extracted.
263
- *
264
- * @returns A promise that resolves to the response data containing the extracted structured data.
265
- *
266
- * @throws Will throw an error if the token is null, if 'data' or 'format' are not defined,
267
- * or if an error occurs during the request to the extraction endpoint.
268
- */
269
- const extractWithTextly = async (token, data) => {
270
- if (token === null)
271
- throw customError(3000, "Invalid private token.");
272
- if (!data.data)
273
- throw customError(1500, "No data provided.");
274
- if (!data.format)
275
- throw customError(1500, "No format provided.");
276
- try {
277
- const response = await config_1.axiosApiUrl.post("/private/textly/extract", data, { headers: { "Content-Type": "application/json", "Authorization": token } });
278
- return response.data;
279
- }
280
- catch (error) {
281
- throw customError(5000, error.response?.data?.message || error.message);
282
- }
283
- };
284
- exports.extractWithTextly = extractWithTextly;
@@ -1,102 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.isValidPwd = exports.satinizer = exports.getPrayerTimes = void 0;
37
- const config_1 = __importStar(require("../config/index.cjs"));
38
- const customError = (code, message) => {
39
- return Object.assign(new Error(), { code, message: `[${config_1.default.lib.name}] ${message}` });
40
- };
41
- const getPrayerTimes = async (data) => {
42
- const { lat, lon } = data;
43
- if (lat === undefined || lon === undefined)
44
- throw customError(1000, "You must provide a latitude and longitude.");
45
- try {
46
- const response = await config_1.axiosApiUrl.get("/public/islam/prayertimes", { params: data });
47
- return response.data;
48
- }
49
- catch (error) {
50
- throw customError(5000, error.response?.data?.message || error.message);
51
- }
52
- };
53
- exports.getPrayerTimes = getPrayerTimes;
54
- const satinizer = async (data) => {
55
- const { input } = data;
56
- if (input === undefined)
57
- throw customError(1000, "You must specify at least the input.");
58
- try {
59
- const response = await config_1.axiosApiUrl.get("/public/inputSatinizer", { params: { input: encodeURIComponent(input) } });
60
- return response.data;
61
- }
62
- catch (error) {
63
- throw customError(5000, error.response?.data?.message || error.message);
64
- }
65
- };
66
- exports.satinizer = satinizer;
67
- const isValidPwd = async (data) => {
68
- let { email, password, bannedWords, min, max } = data;
69
- if (password === undefined)
70
- throw customError(1000, "You must specify at least the password.");
71
- const params = { password: encodeURIComponent(password) };
72
- if (email) {
73
- if (!/^[a-zA-Z0-9._\-+]+@?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test(email))
74
- throw customError(1500, "If you provide an email address it must be valid.");
75
- params.email = encodeURIComponent(email);
76
- }
77
- if (bannedWords) {
78
- if (typeof bannedWords === "string")
79
- bannedWords = bannedWords.slice(1, -1).trim().split(",").map(item => item.trim());
80
- if (!Array.isArray(bannedWords) || bannedWords.length > 10)
81
- throw customError(1500, "If you provide a list of banned words; the list may not exceed 10 words and must be of array type.");
82
- if (!bannedWords.every(word => typeof word === "string") || new Set(bannedWords).size !== bannedWords.length)
83
- throw customError(1500, "If you provide a list of banned words; all elements must be non-repeated strings.");
84
- params.bannedWords = bannedWords;
85
- }
86
- if (min !== undefined && (!Number.isInteger(min) || min < 8 || min > 32))
87
- throw customError(1500, "If you provide a minimum it must be valid.");
88
- if (max !== undefined && (!Number.isInteger(max) || max < 32 || max > 100))
89
- throw customError(1500, "If you provide a maximum it must be valid.");
90
- if (min !== undefined)
91
- params.min = min;
92
- if (max !== undefined)
93
- params.max = max;
94
- try {
95
- const response = await config_1.axiosApiUrl.get("/public/validPwd", { params });
96
- return response.data;
97
- }
98
- catch (error) {
99
- throw customError(5000, error.response?.data?.message || error.message);
100
- }
101
- };
102
- exports.isValidPwd = isValidPwd;
@@ -1,240 +0,0 @@
1
- import path from "path";
2
- import React from "react";
3
- import fs from "fs/promises";
4
- import { twi } from "tw-to-css";
5
- import { render } from "@react-email/render";
6
- import config, { axiosApiUrl } from "../config/index.js";
7
- const customError = (code, message) => {
8
- return Object.assign(new Error(), { code, message: `[${config.lib.name}] ${message}` });
9
- };
10
- const convertTailwindToInlineCss = (htmlContent) => {
11
- return htmlContent.replace(/class="([^"]+)"( style="([^"]+)")?/g, (match, classList, _, existingStyle) => {
12
- const compiledStyles = twi(classList, { minify: true, merge: true });
13
- return match.replace(/class="[^"]+"/, "").replace(/ style="[^"]+"/, "").concat(` style="${existingStyle ? `${existingStyle.trim().slice(0, -1)}; ${compiledStyles}` : compiledStyles}"`);
14
- });
15
- };
16
- /**
17
- * Validates the provided data using a secure verification endpoint.
18
- *
19
- * @param token - A string or null representing the authentication token. Must not be null.
20
- * @param data - An object adhering to the Validator interface, containing at least one of the following fields:
21
- * url, email, phone, domain, creditCard, ip, wallet or user agent.
22
- *
23
- * @returns A promise that resolves to the response data from the verification endpoint.
24
- *
25
- * @throws Will throw an error if the token is null, if none of the required fields are present in the data,
26
- * or if an error occurs during the verification request.
27
- */
28
- export const isValidData = async (token, data) => {
29
- if (token === null)
30
- throw customError(3000, "Invalid private token.");
31
- if (!Object.keys(data).some((key) => ["url", "email", "phone", "domain", "creditCard", "ip", "wallet", "userAgent"].includes(key) && data.hasOwnProperty(key)))
32
- throw customError(1500, "You must provide at least one parameter.");
33
- try {
34
- const response = await axiosApiUrl.post("/private/secure/verify", data, { headers: { "Content-Type": "application/json", "Authorization": token } });
35
- return response.data;
36
- }
37
- catch (error) {
38
- const statusCode = error.response?.status || 500;
39
- const errorMessage = error.response?.data?.message || error.message;
40
- const errorDetails = JSON.stringify(error.response?.data || {});
41
- throw customError(5000, `Error ${statusCode}: ${errorMessage}. Details: ${errorDetails}`);
42
- }
43
- };
44
- /**
45
- * Validates an email using a secure verification endpoint.
46
- *
47
- * @param {string | null} token - Authentication token (required).
48
- * @param {Interfaces.EmailValidator} email - Email to validate.
49
- * @param {Interfaces.EmailValidatorRules} [rules] - Deny rules. Defaults to ["FRAUD", "INVALID", "NO_MX_RECORDS", "NO_REPLY_EMAIL"].
50
- *
51
- * Deny rules (some are premium ⚠️):
52
- * - "FRAUD", "INVALID", "NO_MX_RECORDS" ⚠️, "PROXIED_EMAIL" ⚠️, "FREE_SUBDOMAIN" ⚠️,
53
- * "PERSONAL_EMAIL", "CORPORATE_EMAIL", "NO_REPLY_EMAIL", "ROLE_ACCOUNT", "NO_REACHABLE", "HIGH_RISK_SCORE" ⚠️
54
- *
55
- * @returns {Promise<boolean>} True if the email passes all deny rules, false otherwise.
56
- * @throws Error if token is null, rules are empty, or request fails.
57
- *
58
- * @example
59
- * const valid = await isValidEmail(apiToken, "user@example.com", { deny: ["FRAUD", "NO_MX_RECORDS"] });
60
- */
61
- export const isValidEmail = async (token, email, rules) => {
62
- if (token === null)
63
- throw customError(3000, "Invalid private token.");
64
- if (rules.deny.length === 0)
65
- throw customError(1500, "You must provide at least one deny rule.");
66
- try {
67
- const responseEmail = (await axiosApiUrl.post("/private/secure/verify", {
68
- email,
69
- plugins: [
70
- rules.deny.includes("NO_MX_RECORDS") ? "mxRecords" : undefined,
71
- rules.deny.includes("NO_REACHABLE") ? "reachability" : undefined,
72
- rules.deny.includes("HIGH_RISK_SCORE") ? "riskScore" : undefined
73
- ]
74
- }, { headers: { "Content-Type": "application/json", "Authorization": token } })).data.email;
75
- let reasons = [];
76
- if (rules.deny.includes("INVALID") && !responseEmail.valid)
77
- reasons.push("INVALID");
78
- if (rules.deny.includes("FRAUD") && responseEmail.fraud)
79
- reasons.push("FRAUD");
80
- if (rules.deny.includes("PROXIED_EMAIL") && responseEmail.proxiedEmail)
81
- reasons.push("PROXIED_EMAIL");
82
- if (rules.deny.includes("FREE_SUBDOMAIN") && responseEmail.freeSubdomain)
83
- reasons.push("FREE_SUBDOMAIN");
84
- if (rules.deny.includes("PERSONAL_EMAIL") && !responseEmail.corporate)
85
- reasons.push("PERSONAL_EMAIL");
86
- if (rules.deny.includes("CORPORATE_EMAIL") && responseEmail.corporate)
87
- reasons.push("CORPORATE_EMAIL");
88
- if (rules.deny.includes("NO_MX_RECORDS") && responseEmail.plugins.mxRecords.length === 0)
89
- reasons.push("NO_MX_RECORDS");
90
- if (rules.deny.includes("NO_REPLY_EMAIL") && responseEmail.noReply)
91
- reasons.push("NO_REPLY_EMAIL");
92
- if (rules.deny.includes("ROLE_ACCOUNT") && responseEmail.plugins.roleAccount)
93
- reasons.push("ROLE_ACCOUNT");
94
- if (rules.deny.includes("NO_REACHABLE") && !responseEmail.plugins.reachable)
95
- reasons.push("NO_REACHABLE");
96
- if (rules.deny.includes("HIGH_RISK_SCORE") && responseEmail.plugins.riskScore >= 80)
97
- reasons.push("HIGH_RISK_SCORE");
98
- return {
99
- email: responseEmail.email,
100
- allow: reasons.length === 0,
101
- reasons,
102
- response: responseEmail
103
- };
104
- }
105
- catch (error) {
106
- const statusCode = error.response?.status || 500;
107
- const errorMessage = error.response?.data?.message || error.message;
108
- const errorDetails = JSON.stringify(error.response?.data || {});
109
- throw customError(5000, `Error ${statusCode}: ${errorMessage}. Details: ${errorDetails}`);
110
- }
111
- };
112
- /**
113
- * Sends an email using a secure sending endpoint.
114
- *
115
- * @param token - A string or null representing the authentication token. Must not be null.
116
- * @param data - An object adhering to the SendEmail interface, containing the following fields:
117
- * 'from', 'to', 'subject', 'html' or 'react', and optionally 'attachments', 'options', 'priority', 'waitToResponse', and 'composeTailwindClasses'.
118
- *
119
- * @returns A promise that resolves to the response data from the sending endpoint.
120
- *
121
- * @throws Will throw an error if the token is null, if any of the required fields are missing,
122
- * if the 'react' field is not a valid React element, if the 'attachments' field exceeds the maximum allowed size of 40 MB,
123
- * or if an error occurs during the sending request.
124
- */
125
- export const sendEmail = async (token, data) => {
126
- if (token === null)
127
- throw customError(3000, "Invalid private token.");
128
- if (!data.from)
129
- throw customError(1500, "You must provide an email address from which the following will be sent.");
130
- if (!data.to)
131
- throw customError(1500, "You must provide an email to be sent to.");
132
- if (!data.subject)
133
- throw customError(1500, "You must provide a subject for the email to be sent.");
134
- if (!data.html && !data.react && !React.isValidElement(data.react))
135
- throw customError(1500, "You must provide HTML or a React component.");
136
- if (data.html && data.react)
137
- throw customError(1500, "You must provide only HTML or a React component, not both.");
138
- try {
139
- if (data.react) {
140
- //@ts-ignore
141
- data.html = await render(data.react);
142
- delete data.react;
143
- }
144
- if (data.options && data.options.composeTailwindClasses) {
145
- data.html = convertTailwindToInlineCss(data.html);
146
- delete data.options.composeTailwindClasses;
147
- }
148
- }
149
- catch (error) {
150
- throw customError(1500, `An error occurred while rendering your React component. Details: ${error}`);
151
- }
152
- try {
153
- let totalSize = 0;
154
- if (data.attachments && Array.isArray(data.attachments)) {
155
- const processedAttachments = await Promise.all(data.attachments.map(async (attachment) => {
156
- if ((attachment.path && attachment.content) || (!attachment.path && !attachment.content))
157
- throw customError(1500, "You must provide either 'path' or 'content', not both.");
158
- let contentBuffer;
159
- if (attachment.path)
160
- contentBuffer = await fs.readFile(path.resolve(attachment.path));
161
- else if (attachment.content)
162
- contentBuffer = attachment.content instanceof Buffer ? attachment.content : Buffer.from(attachment.content);
163
- totalSize += Buffer.byteLength(contentBuffer);
164
- if (totalSize > 40 * 1024 * 1024)
165
- throw customError(1500, "Attachments exceed the maximum allowed size of 40 MB.");
166
- return {
167
- filename: attachment.filename || path.basename(attachment.path || ""),
168
- content: contentBuffer,
169
- cid: attachment.cid || attachment.filename
170
- };
171
- }));
172
- data.attachments = processedAttachments;
173
- }
174
- const response = await axiosApiUrl.post("/private/sender/sendEmail", data, { headers: { "Authorization": token } });
175
- return response.data;
176
- }
177
- catch (error) {
178
- throw customError(5000, error.response?.data?.message || error.message);
179
- }
180
- };
181
- /**
182
- * Retrieves a random number within a specified range using a secure endpoint.
183
- *
184
- * @param token - A string or null representing the authentication token. Must not be null.
185
- * @param data - An object adhering to the SRNG interface, containing 'min' and 'max' fields,
186
- * which define the inclusive range within which the random number should be generated.
187
- *
188
- * @returns A promise that resolves to the response data containing the random number.
189
- *
190
- * @throws Will throw an error if the token is null, if 'min' or 'max' are not defined,
191
- * if 'min' is not less than 'max', if 'min' or 'max' are out of the allowed range,
192
- * or if an error occurs during the request to the random number generator endpoint.
193
- */
194
- export const getRandom = async (token, data) => {
195
- if (token === null)
196
- throw customError(3000, "Invalid private token.");
197
- if (!data.min || !data.max)
198
- throw customError(1500, "Both 'min' and 'max' parameters must be defined.");
199
- if (data.min >= data.max)
200
- throw customError(1500, "'min' must be less than 'max'.");
201
- if (data.min < -1000000000 || data.min > 1000000000)
202
- throw customError(1500, "'min' must be an integer in the interval [-1000000000}, 1000000000].");
203
- if (data.max < -1000000000 || data.max > 1000000000)
204
- throw customError(1500, "'max' must be an integer in the interval [-1000000000}, 1000000000].");
205
- try {
206
- const response = await axiosApiUrl.post("/private/srng", data, { headers: { "Content-Type": "application/json", "Authorization": token } });
207
- return response.data;
208
- }
209
- catch (error) {
210
- throw customError(5000, error.response?.data?.message || error.message);
211
- }
212
- };
213
- /**
214
- * Extracts structured data from a given string using a secure endpoint.
215
- *
216
- * @param token - A string or null representing the authentication token. Must not be null.
217
- * @param data - An object adhering to the ExtractWithTextly interface, containing 'data' and 'format' fields.
218
- * The 'data' field is the string from which structured data should be extracted.
219
- * The 'format' field is an object defining the structure of the data to be extracted.
220
- *
221
- * @returns A promise that resolves to the response data containing the extracted structured data.
222
- *
223
- * @throws Will throw an error if the token is null, if 'data' or 'format' are not defined,
224
- * or if an error occurs during the request to the extraction endpoint.
225
- */
226
- export const extractWithTextly = async (token, data) => {
227
- if (token === null)
228
- throw customError(3000, "Invalid private token.");
229
- if (!data.data)
230
- throw customError(1500, "No data provided.");
231
- if (!data.format)
232
- throw customError(1500, "No format provided.");
233
- try {
234
- const response = await axiosApiUrl.post("/private/textly/extract", data, { headers: { "Content-Type": "application/json", "Authorization": token } });
235
- return response.data;
236
- }
237
- catch (error) {
238
- throw customError(5000, error.response?.data?.message || error.message);
239
- }
240
- };