dymo-api 1.2.6 → 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.
@@ -24,6 +24,15 @@ const isValidEmail = async (axiosClient, email, rules) => {
24
24
  throw (0, basics_1.customError)(3000, "Invalid private token.");
25
25
  if (rules.deny.length === 0)
26
26
  throw (0, basics_1.customError)(1500, "You must provide at least one deny rule.");
27
+ if (rules.mode === "DRY_RUN") {
28
+ console.warn("[Dymo API] DRY_RUN mode is enabled. No requests with real data will be processed until you switch to LIVE mode.");
29
+ return {
30
+ email,
31
+ allow: true,
32
+ reasons: [],
33
+ response: "CHANGE TO LIVE MODE"
34
+ };
35
+ }
27
36
  try {
28
37
  const responseEmail = (await axiosClient.post("/private/secure/verify", {
29
38
  email,
@@ -0,0 +1,74 @@
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.protectReq = void 0;
37
+ const basics_1 = require("../../../../utils/basics.cjs");
38
+ const requestHandler_1 = require("./requestHandler.cjs");
39
+ const Interfaces = __importStar(require("../../../../lib/types/interfaces.cjs"));
40
+ const isWellKnownBot = (ua) => {
41
+ return Object.values(Interfaces.categories).flat().includes(ua);
42
+ };
43
+ const protectReq = async (axiosClient, req, rules) => {
44
+ if (!axiosClient.defaults.headers?.Authorization)
45
+ throw (0, basics_1.customError)(3000, "Invalid private token.");
46
+ const reqData = (0, requestHandler_1.handleRequest)(req);
47
+ if (!reqData.userAgent || !reqData.ip)
48
+ throw (0, basics_1.customError)(1500, "You must provide user agent and ip.");
49
+ if (rules.mode === "DRY_RUN") {
50
+ console.warn("[Dymo API] DRY_RUN mode is enabled. No requests with real data will be processed until you switch to LIVE mode.");
51
+ return {
52
+ ip: reqData.ip,
53
+ userAgent: reqData.userAgent,
54
+ allow: true,
55
+ reasons: []
56
+ };
57
+ }
58
+ try {
59
+ const response = await axiosClient.post("/private/waf/verifyRequest", {
60
+ ip: reqData.ip,
61
+ userAgent: reqData.userAgent,
62
+ allowBots: rules.allowBots,
63
+ deny: rules.deny
64
+ }, { headers: { "Content-Type": "application/json" } });
65
+ return response.data;
66
+ }
67
+ catch (error) {
68
+ const statusCode = error.response?.status || 500;
69
+ const errorMessage = error.response?.data?.message || error.message;
70
+ const errorDetails = JSON.stringify(error.response?.data || {});
71
+ throw (0, basics_1.customError)(5000, `Error ${statusCode}: ${errorMessage}. Details: ${errorDetails}`);
72
+ }
73
+ };
74
+ exports.protectReq = protectReq;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleRequest = void 0;
4
+ // Helpers.
5
+ const getUserAgent = (req) => {
6
+ return req.headers?.["user-agent"] || req.headers?.["User-Agent"];
7
+ };
8
+ const getIp = (req) => {
9
+ return (req.ip ||
10
+ req.headers?.["x-forwarded-for"] ||
11
+ req.connection?.remoteAddress ||
12
+ req.socket?.remoteAddress ||
13
+ req.req?.socket?.remoteAddress);
14
+ };
15
+ const handleRequest = (req) => {
16
+ return {
17
+ body: req.body,
18
+ userAgent: getUserAgent(req),
19
+ ip: getIp(req)
20
+ };
21
+ };
22
+ exports.handleRequest = handleRequest;
@@ -18,4 +18,5 @@ __exportStar(require("./functions/extractWithTextly/index.cjs"), exports);
18
18
  __exportStar(require("./functions/getRandom/index.cjs"), exports);
19
19
  __exportStar(require("./functions/isValidData/index.cjs"), exports);
20
20
  __exportStar(require("./functions/isValidEmail/index.cjs"), exports);
21
+ __exportStar(require("./functions/protectReq/index.cjs"), exports);
21
22
  __exportStar(require("./functions/sendEmail/index.cjs"), exports);
@@ -64,9 +64,9 @@ class DymoAPI {
64
64
  */
65
65
  constructor({ rootApiKey = null, apiKey = null, baseUrl = "https://api.tpeoficial.com", serverEmailConfig = undefined, rules = {} } = {}) {
66
66
  this.rules = {
67
- bot: { mode: "LIVE", allow: [] },
68
67
  email: { mode: "LIVE", deny: ["FRAUD", "INVALID", "NO_MX_RECORDS", "NO_REPLY_EMAIL"] },
69
68
  sensitiveInfo: { mode: "LIVE", deny: ["EMAIL", "PHONE", "CREDIT_CARD"] },
69
+ waf: { mode: "LIVE", allowBots: ["CURL", "CATEGORY:SEARCH_ENGINE", "CATEGORY:PREVIEW"], deny: ["FRAUD", "TOR_NETWORK"] },
70
70
  ...rules
71
71
  };
72
72
  this.rootApiKey = rootApiKey;
@@ -127,12 +127,33 @@ class DymoAPI {
127
127
  * @example
128
128
  * const valid = await dymoClient.isValidEmail("user@example.com", { deny: ["FRAUD", "NO_MX_RECORDS"] });
129
129
  *
130
- * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
130
+ * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/request-verifier)
131
131
  */
132
132
  async isValidEmail(email, rules = this.rules.email) {
133
133
  return await PrivateAPI.isValidEmail(this.axiosClient, email, rules);
134
134
  }
135
135
  ;
136
+ /**
137
+ * Protects the given request against the configured rules.
138
+ *
139
+ * This method requires either the root API key or the API key to be set.
140
+ * If neither is set, it will throw an error.
141
+ *
142
+ * @param {Object} req - The request object to be protected.
143
+ * @param {Interfaces.WafRules} [rules] - Optional rules for protection. Some rules are premium features.
144
+ * @returns {Promise<Interfaces.HTTPRequest>} Resolves with the protected request.
145
+ * @important
146
+ * **⚠️ This is a [PREMIUM](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier) and BETA feature.**
147
+ * @throws Will throw an error if protection cannot be performed.
148
+ *
149
+ * @example
150
+ * const protectedReq = await dymoClient.protectReq(req);
151
+ *
152
+ * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
153
+ */
154
+ async protectReq(req, rules = this.rules.waf) {
155
+ return await PrivateAPI.protectReq(this.axiosClient, req, rules);
156
+ }
136
157
  /**
137
158
  * Sends an email using the configured email client settings.
138
159
  *
@@ -19,4 +19,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
19
19
  ;
20
20
  ;
21
21
  __exportStar(require("./rules.cjs"), exports);
22
+ __exportStar(require("./primitives.cjs"), exports);
22
23
  __exportStar(require("./data-verifier.cjs"), exports);
24
+ __exportStar(require("./well-known-bots.cjs"), exports);
@@ -21,6 +21,15 @@ export const isValidEmail = async (axiosClient, email, rules) => {
21
21
  throw customError(3000, "Invalid private token.");
22
22
  if (rules.deny.length === 0)
23
23
  throw customError(1500, "You must provide at least one deny rule.");
24
+ if (rules.mode === "DRY_RUN") {
25
+ console.warn("[Dymo API] DRY_RUN mode is enabled. No requests with real data will be processed until you switch to LIVE mode.");
26
+ return {
27
+ email,
28
+ allow: true,
29
+ reasons: [],
30
+ response: "CHANGE TO LIVE MODE"
31
+ };
32
+ }
24
33
  try {
25
34
  const responseEmail = (await axiosClient.post("/private/secure/verify", {
26
35
  email,
@@ -0,0 +1,37 @@
1
+ import { customError } from "../../../../utils/basics.js";
2
+ import { handleRequest } from "./requestHandler.js";
3
+ import * as Interfaces from "../../../../lib/types/interfaces.js";
4
+ const isWellKnownBot = (ua) => {
5
+ return Object.values(Interfaces.categories).flat().includes(ua);
6
+ };
7
+ export const protectReq = async (axiosClient, req, rules) => {
8
+ if (!axiosClient.defaults.headers?.Authorization)
9
+ throw customError(3000, "Invalid private token.");
10
+ const reqData = handleRequest(req);
11
+ if (!reqData.userAgent || !reqData.ip)
12
+ throw customError(1500, "You must provide user agent and ip.");
13
+ if (rules.mode === "DRY_RUN") {
14
+ console.warn("[Dymo API] DRY_RUN mode is enabled. No requests with real data will be processed until you switch to LIVE mode.");
15
+ return {
16
+ ip: reqData.ip,
17
+ userAgent: reqData.userAgent,
18
+ allow: true,
19
+ reasons: []
20
+ };
21
+ }
22
+ try {
23
+ const response = await axiosClient.post("/private/waf/verifyRequest", {
24
+ ip: reqData.ip,
25
+ userAgent: reqData.userAgent,
26
+ allowBots: rules.allowBots,
27
+ deny: rules.deny
28
+ }, { headers: { "Content-Type": "application/json" } });
29
+ return response.data;
30
+ }
31
+ catch (error) {
32
+ const statusCode = error.response?.status || 500;
33
+ const errorMessage = error.response?.data?.message || error.message;
34
+ const errorDetails = JSON.stringify(error.response?.data || {});
35
+ throw customError(5000, `Error ${statusCode}: ${errorMessage}. Details: ${errorDetails}`);
36
+ }
37
+ };
@@ -0,0 +1,18 @@
1
+ // Helpers.
2
+ const getUserAgent = (req) => {
3
+ return req.headers?.["user-agent"] || req.headers?.["User-Agent"];
4
+ };
5
+ const getIp = (req) => {
6
+ return (req.ip ||
7
+ req.headers?.["x-forwarded-for"] ||
8
+ req.connection?.remoteAddress ||
9
+ req.socket?.remoteAddress ||
10
+ req.req?.socket?.remoteAddress);
11
+ };
12
+ export const handleRequest = (req) => {
13
+ return {
14
+ body: req.body,
15
+ userAgent: getUserAgent(req),
16
+ ip: getIp(req)
17
+ };
18
+ };
@@ -2,4 +2,5 @@ export * from "./functions/extractWithTextly";
2
2
  export * from "./functions/getRandom";
3
3
  export * from "./functions/isValidData";
4
4
  export * from "./functions/isValidEmail";
5
+ export * from "./functions/protectReq";
5
6
  export * from "./functions/sendEmail";
@@ -26,9 +26,9 @@ class DymoAPI {
26
26
  */
27
27
  constructor({ rootApiKey = null, apiKey = null, baseUrl = "https://api.tpeoficial.com", serverEmailConfig = undefined, rules = {} } = {}) {
28
28
  this.rules = {
29
- bot: { mode: "LIVE", allow: [] },
30
29
  email: { mode: "LIVE", deny: ["FRAUD", "INVALID", "NO_MX_RECORDS", "NO_REPLY_EMAIL"] },
31
30
  sensitiveInfo: { mode: "LIVE", deny: ["EMAIL", "PHONE", "CREDIT_CARD"] },
31
+ waf: { mode: "LIVE", allowBots: ["CURL", "CATEGORY:SEARCH_ENGINE", "CATEGORY:PREVIEW"], deny: ["FRAUD", "TOR_NETWORK"] },
32
32
  ...rules
33
33
  };
34
34
  this.rootApiKey = rootApiKey;
@@ -89,12 +89,33 @@ class DymoAPI {
89
89
  * @example
90
90
  * const valid = await dymoClient.isValidEmail("user@example.com", { deny: ["FRAUD", "NO_MX_RECORDS"] });
91
91
  *
92
- * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
92
+ * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/request-verifier)
93
93
  */
94
94
  async isValidEmail(email, rules = this.rules.email) {
95
95
  return await PrivateAPI.isValidEmail(this.axiosClient, email, rules);
96
96
  }
97
97
  ;
98
+ /**
99
+ * Protects the given request against the configured rules.
100
+ *
101
+ * This method requires either the root API key or the API key to be set.
102
+ * If neither is set, it will throw an error.
103
+ *
104
+ * @param {Object} req - The request object to be protected.
105
+ * @param {Interfaces.WafRules} [rules] - Optional rules for protection. Some rules are premium features.
106
+ * @returns {Promise<Interfaces.HTTPRequest>} Resolves with the protected request.
107
+ * @important
108
+ * **⚠️ This is a [PREMIUM](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier) and BETA feature.**
109
+ * @throws Will throw an error if protection cannot be performed.
110
+ *
111
+ * @example
112
+ * const protectedReq = await dymoClient.protectReq(req);
113
+ *
114
+ * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
115
+ */
116
+ async protectReq(req, rules = this.rules.waf) {
117
+ return await PrivateAPI.protectReq(this.axiosClient, req, rules);
118
+ }
98
119
  /**
99
120
  * Sends an email using the configured email client settings.
100
121
  *
@@ -3,4 +3,6 @@
3
3
  ;
4
4
  ;
5
5
  export * from "./rules";
6
+ export * from "./primitives";
6
7
  export * from "./data-verifier";
8
+ export * from "./well-known-bots";
@@ -0,0 +1,3 @@
1
+ import { type AxiosInstance } from "axios";
2
+ import * as Interfaces from "../../../../lib/types/interfaces";
3
+ export declare const protectReq: <T>(axiosClient: AxiosInstance, req: Interfaces.HTTPRequest, rules: Interfaces.WafRules) => Promise<any>;
@@ -0,0 +1,22 @@
1
+ type GenericRequest<T = any> = {
2
+ body?: T;
3
+ headers?: Record<string, any>;
4
+ ip?: string;
5
+ connection?: {
6
+ remoteAddress?: string;
7
+ };
8
+ socket?: {
9
+ remoteAddress?: string;
10
+ };
11
+ req?: {
12
+ socket?: {
13
+ remoteAddress?: string;
14
+ };
15
+ };
16
+ };
17
+ export declare const handleRequest: <T = any>(req: GenericRequest<T>) => {
18
+ body: T | undefined;
19
+ userAgent: string | undefined;
20
+ ip: string | undefined;
21
+ };
22
+ export {};
@@ -2,4 +2,5 @@ export * from "./functions/extractWithTextly";
2
2
  export * from "./functions/getRandom";
3
3
  export * from "./functions/isValidData";
4
4
  export * from "./functions/isValidEmail";
5
+ export * from "./functions/protectReq";
5
6
  export * from "./functions/sendEmail";
@@ -68,9 +68,28 @@ declare class DymoAPI {
68
68
  * @example
69
69
  * const valid = await dymoClient.isValidEmail("user@example.com", { deny: ["FRAUD", "NO_MX_RECORDS"] });
70
70
  *
71
- * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
71
+ * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/request-verifier)
72
72
  */
73
73
  isValidEmail(email: Interfaces.EmailValidator, rules?: Interfaces.EmailValidatorRules): Promise<Interfaces.EmailValidatorResponse>;
74
+ /**
75
+ * Protects the given request against the configured rules.
76
+ *
77
+ * This method requires either the root API key or the API key to be set.
78
+ * If neither is set, it will throw an error.
79
+ *
80
+ * @param {Object} req - The request object to be protected.
81
+ * @param {Interfaces.WafRules} [rules] - Optional rules for protection. Some rules are premium features.
82
+ * @returns {Promise<Interfaces.HTTPRequest>} Resolves with the protected request.
83
+ * @important
84
+ * **⚠️ This is a [PREMIUM](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier) and BETA feature.**
85
+ * @throws Will throw an error if protection cannot be performed.
86
+ *
87
+ * @example
88
+ * const protectedReq = await dymoClient.protectReq(req);
89
+ *
90
+ * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
91
+ */
92
+ protectReq(req: Interfaces.HTTPRequest, rules?: Interfaces.WafRules): Promise<any>;
74
93
  /**
75
94
  * Sends an email using the configured email client settings.
76
95
  *
@@ -163,4 +163,6 @@ export interface ExtractWithTextly {
163
163
  };
164
164
  }
165
165
  export * from "./rules";
166
+ export * from "./primitives";
166
167
  export * from "./data-verifier";
168
+ export * from "./well-known-bots";
@@ -9,3 +9,10 @@ export interface CreditCard {
9
9
  cvc?: string | number;
10
10
  cvv?: string | number;
11
11
  }
12
+ export interface HTTPRequest {
13
+ url: string;
14
+ method: string | "GET" | "POST" | "PUT" | "DELETE";
15
+ headers?: Record<string, string>;
16
+ body?: string | object | null;
17
+ [key: string]: any;
18
+ }
@@ -1,9 +1,11 @@
1
1
  import * as WellKnownBots from "./well-known-bots";
2
2
  import { NegativeEmailRules, NegativeSensitiveInfoRules } from "./data-verifier";
3
3
  type Mode = "LIVE" | "DRY_RUN";
4
- export interface BotRules {
4
+ type NegativeWafRules = "FRAUD" | "VPN" | "PROXY" | "TOR_NETWORK";
5
+ export interface WafRules {
5
6
  mode?: Mode;
6
- allow?: WellKnownBots.WellKnownBotOrCategory[];
7
+ allowBots?: WellKnownBots.WellKnownBotOrCategory[];
8
+ deny?: NegativeWafRules[];
7
9
  }
8
10
  export interface EmailValidatorRules {
9
11
  mode?: Mode;
@@ -14,8 +16,8 @@ export interface SensitiveInfoRules {
14
16
  deny: NegativeSensitiveInfoRules[];
15
17
  }
16
18
  export interface Rules {
17
- bot?: BotRules;
18
19
  email?: EmailValidatorRules;
19
20
  sensitiveInfo?: SensitiveInfoRules;
21
+ waf?: WafRules;
20
22
  }
21
23
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dymo-api",
3
- "version": "1.2.06",
3
+ "version": "1.2.7",
4
4
  "description": "Flow system for Dymo API.",
5
5
  "main": "dist/cjs/dymo-api.js",
6
6
  "module": "dist/esm/dymo-api.js",