dymo-api 1.2.29 → 1.2.31

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.
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResilienceManager = void 0;
4
+ class RateLimitManager {
5
+ constructor() {
6
+ this.tracker = {};
7
+ }
8
+ static getInstance() {
9
+ if (!RateLimitManager.instance)
10
+ RateLimitManager.instance = new RateLimitManager();
11
+ return RateLimitManager.instance;
12
+ }
13
+ ;
14
+ updateRateLimit(clientId, headers) {
15
+ if (!this.tracker[clientId])
16
+ this.tracker[clientId] = {};
17
+ const limitInfo = this.tracker[clientId];
18
+ if (headers["x-ratelimit-limit-requests"])
19
+ limitInfo.limit = parseInt(headers["x-ratelimit-limit-requests"]);
20
+ if (headers["x-ratelimit-remaining-requests"])
21
+ limitInfo.remaining = parseInt(headers["x-ratelimit-remaining-requests"]);
22
+ if (headers["x-ratelimit-reset-requests"])
23
+ limitInfo.resetTime = headers["x-ratelimit-reset-requests"];
24
+ if (headers["retry-after"])
25
+ limitInfo.retryAfter = parseInt(headers["retry-after"]);
26
+ limitInfo.lastUpdated = Date.now();
27
+ }
28
+ ;
29
+ isRateLimited(clientId) {
30
+ const limitInfo = this.tracker[clientId];
31
+ return limitInfo?.remaining !== undefined && limitInfo.remaining <= 0;
32
+ }
33
+ ;
34
+ getRetryAfter(clientId) {
35
+ return this.tracker[clientId]?.retryAfter;
36
+ }
37
+ ;
38
+ clearExpiredLimits() {
39
+ const now = Date.now();
40
+ Object.keys(this.tracker).forEach(clientId => {
41
+ const limitInfo = this.tracker[clientId];
42
+ if (limitInfo.lastUpdated && (now - limitInfo.lastUpdated) > 300000)
43
+ delete this.tracker[clientId];
44
+ });
45
+ }
46
+ ;
47
+ }
48
+ ;
49
+ class ResilienceManager {
50
+ constructor(config = {}, clientId = "default") {
51
+ this.config = {
52
+ fallbackEnabled: config.fallbackEnabled ?? false,
53
+ retryAttempts: Math.max(0, config.retryAttempts ?? 2), // Number of additional retries
54
+ retryDelay: Math.max(0, config.retryDelay ?? 1000)
55
+ };
56
+ this.clientId = clientId;
57
+ this.rateLimitManager = RateLimitManager.getInstance();
58
+ }
59
+ ;
60
+ async executeWithResilience(axiosClient, requestConfig, fallbackData) {
61
+ let lastError;
62
+ const totalAttempts = 1 + this.config.retryAttempts; // 1 normal + N retries
63
+ // Clean up expired rate limits periodically
64
+ this.rateLimitManager.clearExpiredLimits();
65
+ // Check if client is currently rate limited
66
+ if (this.rateLimitManager.isRateLimited(this.clientId)) {
67
+ const retryAfter = this.rateLimitManager.getRetryAfter(this.clientId);
68
+ if (retryAfter) {
69
+ console.warn(`[Dymo API] Client ${this.clientId} is rate limited. Waiting ${retryAfter} seconds...`);
70
+ await this.sleep(retryAfter * 1000);
71
+ }
72
+ }
73
+ for (let attempt = 1; attempt <= totalAttempts; attempt++) {
74
+ try {
75
+ const response = await axiosClient.request(requestConfig);
76
+ // Update rate limit tracking
77
+ this.rateLimitManager.updateRateLimit(this.clientId, response.headers);
78
+ // Check for rate limiting
79
+ if (response.status === 429) {
80
+ const retryAfter = this.rateLimitManager.getRetryAfter(this.clientId);
81
+ if (retryAfter) {
82
+ console.warn(`[Dymo API] Rate limited. Waiting ${retryAfter} seconds (no retries)`);
83
+ await this.sleep(retryAfter * 1000);
84
+ }
85
+ throw new Error(`Rate limited (429) - not retrying`);
86
+ }
87
+ return response.data;
88
+ }
89
+ catch (error) {
90
+ lastError = error;
91
+ let shouldRetry = this.shouldRetry(error);
92
+ const isLastAttempt = attempt === totalAttempts;
93
+ // Don't retry on rate limiting (429)
94
+ if (error.response?.status === 429)
95
+ shouldRetry = false;
96
+ if (!shouldRetry || isLastAttempt) {
97
+ if (this.config.fallbackEnabled && fallbackData) {
98
+ console.warn(`[Dymo API] Request failed after ${attempt} attempts. Using fallback data.`);
99
+ return fallbackData;
100
+ }
101
+ throw error;
102
+ }
103
+ const delay = this.config.retryDelay * Math.pow(2, attempt - 1);
104
+ console.warn(`[Dymo API] Attempt ${attempt} failed. Retrying in ${delay}ms...`);
105
+ await this.sleep(delay);
106
+ }
107
+ }
108
+ throw lastError;
109
+ }
110
+ ;
111
+ shouldRetry(error) {
112
+ const statusCode = error.response?.status;
113
+ const isNetworkError = !error.response && error.code !== "ECONNABORTED";
114
+ const isServerError = statusCode && statusCode >= 500;
115
+ // Retry on: network errors, server errors (5xx)
116
+ // DON'T retry on: rate limiting (429) - handled separately
117
+ // DON'T retry on: client errors (4xx except 429)
118
+ return isNetworkError || isServerError;
119
+ }
120
+ ;
121
+ sleep(ms) {
122
+ return new Promise(resolve => setTimeout(resolve, ms));
123
+ }
124
+ ;
125
+ getConfig() {
126
+ return { ...this.config };
127
+ }
128
+ ;
129
+ getClientId() {
130
+ return this.clientId;
131
+ }
132
+ ;
133
+ }
134
+ exports.ResilienceManager = ResilienceManager;
135
+ ;
@@ -49,6 +49,14 @@ export const isValidPhone = async (axiosClient, phone, rules) => {
49
49
  reasons.push("FRAUD");
50
50
  if (rules.deny.includes("HIGH_RISK_SCORE") && responsePhone.plugins.riskScore >= 80)
51
51
  reasons.push("HIGH_RISK_SCORE");
52
+ // Country block rules.
53
+ for (const rule of rules.deny) {
54
+ if (rule.startsWith("COUNTRY:")) {
55
+ const block = rule.split(":")[1]; // Extract country code.
56
+ if (responsePhone.countryCode === block)
57
+ reasons.push(`COUNTRY:${block}`);
58
+ }
59
+ }
52
60
  return {
53
61
  phone: responsePhone.phone,
54
62
  allow: reasons.length === 0,
@@ -3,25 +3,29 @@ import axios from "axios";
3
3
  import { validBaseURL } from "./utils/basics.js";
4
4
  import * as PublicAPI from "./branches/public/index.js";
5
5
  import * as PrivateAPI from "./branches/private/index.js";
6
+ import { ResilienceManager } from "./lib/resilience/index.js";
7
+ import { FallbackDataGenerator } from "./lib/resilience/fallback.js";
6
8
  class DymoAPI {
7
9
  /**
8
- * @param {Object} options - Options to create the DymoAPI instance.
9
- * @param {string} [options.rootApiKey] - The root API key.
10
- * @param {string} [options.apiKey] - The API key.
11
- * @param {string} [options.baseUrl] - Whether to use a local server instead of the cloud server.
12
- * @param {Object} [options.serverEmailConfig] - The server email config.
13
- * @description
14
- * This is the main class to interact with the Dymo API. It should be
15
- * instantiated with the root API key and the API key. The root API key is
16
- * used to fetch the tokens and the API key is used to authenticate the
17
- * requests.
18
- * @example
19
- * const dymoApi = new DymoAPI({
20
- * rootApiKey: "6bfb7675-6b69-4f8d-9f43-5a6f7f02c6c5",
21
- * apiKey: "dm_4c8b7675-6b69-4f8d-9f43-5a6f7f02c6c5"
22
- * });
23
- */
24
- constructor({ rootApiKey = null, apiKey = null, baseUrl = "https://api.tpeoficial.com", serverEmailConfig = undefined, rules = {} } = {}) {
10
+ * @param {Object} options - Options to create the DymoAPI instance.
11
+ * @param {string} [options.rootApiKey] - The root API key.
12
+ * @param {string} [options.apiKey] - The API key.
13
+ * @param {string} [options.baseUrl] - Whether to use a local server instead of the cloud server.
14
+ * @param {Object} [options.serverEmailConfig] - The server email config.
15
+ * @param {Object} [options.rules] - The rules.
16
+ * @param {Object} [options.resilience] - The resilience config.
17
+ * @description
18
+ * This is the main class to interact with the Dymo API. It should be
19
+ * instantiated with the root API key and the API key. The root API key is
20
+ * used to fetch the tokens and the API key is used to authenticate the
21
+ * requests. Requests are retried once by default with exponential backoff.
22
+ * @example
23
+ * const dymoApi = new DymoAPI({
24
+ * rootApiKey: "6bfb7675-6b69-4f8d-9f43-5a6f7f02c6c5",
25
+ * apiKey: "dm_4c8b7675-6b69-4f8d-9f43-5a6f7f02c6c5"
26
+ * });
27
+ */
28
+ constructor({ rootApiKey = null, apiKey = null, baseUrl = "https://api.tpeoficial.com", serverEmailConfig = undefined, rules = {}, resilience = {} } = {}) {
25
29
  this.rules = {
26
30
  email: { mode: "LIVE", deny: ["FRAUD", "INVALID", "NO_MX_RECORDS", "NO_REPLY_EMAIL"] },
27
31
  ip: { mode: "LIVE", deny: ["FRAUD", "INVALID", "TOR_NETWORK"] },
@@ -34,13 +38,16 @@ class DymoAPI {
34
38
  this.apiKey = apiKey;
35
39
  this.serverEmailConfig = serverEmailConfig;
36
40
  this.baseUrl = baseUrl;
41
+ // Initialize resilience system with client ID
42
+ const clientId = this.apiKey || this.rootApiKey || "anonymous";
43
+ this.resilienceManager = new ResilienceManager(resilience, clientId);
37
44
  // We created the Axios client with the appropriate settings.
38
45
  this.axiosClient = axios.create({
39
46
  baseURL: `${validBaseURL(this.baseUrl)}/v1`,
40
47
  headers: {
41
48
  "User-Agent": "DymoAPISDK/1.0.0",
42
49
  "X-Dymo-SDK-Env": "Node",
43
- "X-Dymo-SDK-Version": "1.2.29"
50
+ "X-Dymo-SDK-Version": "1.2.31"
44
51
  }
45
52
  });
46
53
  // We set the authorization in the Axios client to make requests.
@@ -48,6 +55,14 @@ class DymoAPI {
48
55
  this.axiosClient.defaults.headers.Authorization = `Bearer ${this.rootApiKey || this.apiKey}`;
49
56
  }
50
57
  ;
58
+ getEmailPlugins(rules) {
59
+ return [
60
+ rules.deny.includes("NO_MX_RECORDS") ? "mxRecords" : undefined,
61
+ rules.deny.includes("NO_REACHABLE") ? "reachable" : undefined,
62
+ rules.deny.includes("HIGH_RISK_SCORE") ? "riskScore" : undefined,
63
+ rules.deny.includes("NO_GRAVATAR") ? "gravatar" : undefined
64
+ ].filter(Boolean);
65
+ }
51
66
  // FUNCTIONS / Private.
52
67
  /**
53
68
  * Validates the given data against the configured validation settings.
@@ -73,7 +88,12 @@ class DymoAPI {
73
88
  * [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
74
89
  */
75
90
  async isValidData(data) {
76
- return await PrivateAPI.isValidDataRaw(this.axiosClient, data);
91
+ const fallbackData = FallbackDataGenerator.generateFallbackData("isValidData", data);
92
+ return await this.resilienceManager.executeWithResilience(this.axiosClient, {
93
+ method: "POST",
94
+ url: "/private/secure/verify",
95
+ data
96
+ }, this.resilienceManager.getConfig().fallbackEnabled ? fallbackData : undefined);
77
97
  }
78
98
  ;
79
99
  /**
@@ -99,7 +119,12 @@ class DymoAPI {
99
119
  * [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/data-verifier)
100
120
  */
101
121
  async isValidDataRaw(data) {
102
- return await PrivateAPI.isValidDataRaw(this.axiosClient, data);
122
+ const fallbackData = FallbackDataGenerator.generateFallbackData("isValidDataRaw", data);
123
+ return await this.resilienceManager.executeWithResilience(this.axiosClient, {
124
+ method: "POST",
125
+ url: "/private/secure/verify",
126
+ data
127
+ }, this.resilienceManager.getConfig().fallbackEnabled ? fallbackData : undefined);
103
128
  }
104
129
  ;
105
130
  /**
@@ -121,7 +146,12 @@ class DymoAPI {
121
146
  * @see [Documentation](https://docs.tpeoficial.com/docs/dymo-api/private/email-validation)
122
147
  */
123
148
  async isValidEmail(email, rules = this.rules.email) {
124
- return await PrivateAPI.isValidEmail(this.axiosClient, email, rules);
149
+ const fallbackData = FallbackDataGenerator.generateFallbackData("isValidEmail", email);
150
+ return await this.resilienceManager.executeWithResilience(this.axiosClient, {
151
+ method: "POST",
152
+ url: "/private/secure/verify",
153
+ data: { email, plugins: this.getEmailPlugins(rules) }
154
+ }, this.resilienceManager.getConfig().fallbackEnabled ? fallbackData : undefined);
125
155
  }
126
156
  ;
127
157
  /**
@@ -0,0 +1,423 @@
1
+ export class FallbackDataGenerator {
2
+ static generateFallbackData(method, inputData) {
3
+ switch (method) {
4
+ case "isValidData": return this.generateDataValidationAnalysis(inputData);
5
+ case "isValidEmail": return this.generateEmailValidatorResponse(inputData);
6
+ case "isValidIP": return this.generateIPValidatorResponse(inputData);
7
+ case "isValidPhone": return this.generatePhoneValidatorResponse(inputData);
8
+ case "protectReq": return this.generateHTTPRequest(inputData);
9
+ case "sendEmail": return this.generateEmailStatus();
10
+ case "getRandom": return this.generateSRNSummary(inputData);
11
+ case "extractWithTextly": return this.generateExtractWithTextly(inputData);
12
+ case "getPrayerTimes": return this.generatePrayerTimes(inputData);
13
+ case "satinize": return this.generateSatinizedInputAnalysis(inputData);
14
+ case "isValidPwd": return this.generatePasswordValidationResult(inputData);
15
+ default: throw new Error(`Unknown method for fallback: ${method}`);
16
+ }
17
+ }
18
+ ;
19
+ static validateURL(url) {
20
+ if (!url)
21
+ return false;
22
+ const urlRegex = /^https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w\/_.])*(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?)?$/;
23
+ return urlRegex.test(url);
24
+ }
25
+ ;
26
+ static validateEmail(email) {
27
+ if (!email)
28
+ return false;
29
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
30
+ return emailRegex.test(email);
31
+ }
32
+ ;
33
+ static validateDomain(domain) {
34
+ if (!domain)
35
+ return false;
36
+ const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9](?:\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*$/;
37
+ if (!domainRegex.test(domain))
38
+ return false;
39
+ // Validar que tenga un TLD (último punto + contenido)
40
+ const parts = domain.split('.');
41
+ return parts.length >= 2 && parts[parts.length - 1].length > 0;
42
+ }
43
+ ;
44
+ static validateCreditCard(creditCard) {
45
+ if (!creditCard)
46
+ return false;
47
+ const cardNumber = typeof creditCard === "string" ? creditCard : creditCard?.pan || "";
48
+ if (!cardNumber)
49
+ return false;
50
+ const cardRegex = /^\d{13,19}$/;
51
+ if (!cardRegex.test(cardNumber.replace(/\s/g, "")))
52
+ return false;
53
+ // Luhn algorithm
54
+ const digits = cardNumber.replace(/\s/g, "").split("").map(Number);
55
+ let sum = 0;
56
+ let isEven = false;
57
+ for (let i = digits.length - 1; i >= 0; i--) {
58
+ let digit = digits[i];
59
+ if (isEven) {
60
+ digit *= 2;
61
+ if (digit > 9)
62
+ digit -= 9;
63
+ }
64
+ sum += digit;
65
+ isEven = !isEven;
66
+ }
67
+ return sum % 10 === 0;
68
+ }
69
+ ;
70
+ static validateIP(ip) {
71
+ if (!ip)
72
+ return false;
73
+ const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
74
+ const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
75
+ return ipv4Regex.test(ip) || ipv6Regex.test(ip);
76
+ }
77
+ ;
78
+ static validatePhone(phone) {
79
+ if (!phone)
80
+ return false;
81
+ const phoneRegex = /^\+?[1-9]\d{1,14}$/;
82
+ return phoneRegex.test(phone.replace(/[^\d+]/g, ""));
83
+ }
84
+ ;
85
+ static validateWallet(wallet) {
86
+ if (!wallet)
87
+ return false;
88
+ const bitcoinRegex = /^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/;
89
+ const ethereumRegex = /^0x[a-fA-F0-9]{40}$/;
90
+ return bitcoinRegex.test(wallet) || ethereumRegex.test(wallet);
91
+ }
92
+ ;
93
+ static validateIBAN(iban) {
94
+ if (!iban)
95
+ return false;
96
+ const ibanRegex = /^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$/;
97
+ return ibanRegex.test(iban.replace(/\s/g, "").toUpperCase());
98
+ }
99
+ ;
100
+ static extractDomain(url) {
101
+ if (!url)
102
+ return "";
103
+ try {
104
+ return new URL(url).hostname;
105
+ }
106
+ catch {
107
+ return "";
108
+ }
109
+ }
110
+ ;
111
+ static generateDataValidationAnalysis(inputData) {
112
+ return {
113
+ url: {
114
+ valid: this.validateURL(inputData?.url),
115
+ fraud: false,
116
+ freeSubdomain: false,
117
+ customTLD: false,
118
+ url: inputData?.url || "",
119
+ domain: this.extractDomain(inputData?.url),
120
+ plugins: {
121
+ blocklist: false,
122
+ compromiseDetector: false,
123
+ mxRecords: [],
124
+ nsfw: false,
125
+ reputation: "unknown",
126
+ riskScore: 0,
127
+ torNetwork: false,
128
+ typosquatting: 0,
129
+ urlShortener: false
130
+ }
131
+ },
132
+ email: this.generateEmailDataAnalysis(inputData?.email),
133
+ phone: this.generatePhoneDataAnalysis(inputData?.phone),
134
+ domain: {
135
+ valid: this.validateDomain(inputData?.domain),
136
+ fraud: false,
137
+ freeSubdomain: false,
138
+ customTLD: false,
139
+ domain: inputData?.domain || "",
140
+ plugins: {
141
+ blocklist: false,
142
+ compromiseDetector: false,
143
+ mxRecords: [],
144
+ nsfw: false,
145
+ reputation: "unknown",
146
+ riskScore: 0,
147
+ torNetwork: false,
148
+ typosquatting: 0,
149
+ urlShortener: false
150
+ }
151
+ },
152
+ creditCard: {
153
+ valid: this.validateCreditCard(inputData?.creditCard),
154
+ fraud: false,
155
+ test: false,
156
+ type: "unknown",
157
+ creditCard: typeof inputData?.creditCard === "string" ? inputData.creditCard : inputData?.creditCard?.pan || "",
158
+ plugins: {
159
+ blocklist: false,
160
+ riskScore: 0
161
+ }
162
+ },
163
+ ip: this.generateIPDataAnalysis(inputData?.ip),
164
+ wallet: {
165
+ valid: this.validateWallet(inputData?.wallet),
166
+ fraud: false,
167
+ wallet: inputData?.wallet || "",
168
+ type: "unknown",
169
+ plugins: {
170
+ blocklist: false,
171
+ riskScore: 0,
172
+ torNetwork: false
173
+ }
174
+ },
175
+ userAgent: {
176
+ valid: false,
177
+ fraud: false,
178
+ userAgent: inputData?.userAgent || "",
179
+ bot: true,
180
+ device: { type: "unknown", brand: "unknown" },
181
+ plugins: {
182
+ blocklist: false,
183
+ riskScore: 0
184
+ }
185
+ },
186
+ iban: {
187
+ valid: this.validateIBAN(inputData?.iban),
188
+ fraud: false,
189
+ iban: inputData?.iban || "",
190
+ plugins: {
191
+ blocklist: false,
192
+ riskScore: 0
193
+ }
194
+ }
195
+ };
196
+ }
197
+ ;
198
+ static generateEmailValidatorResponse(inputData) {
199
+ return {
200
+ email: inputData?.email || "",
201
+ allow: this.validateEmail(inputData?.email),
202
+ reasons: this.validateEmail(inputData?.email) ? [] : ["INVALID"],
203
+ response: this.generateEmailDataAnalysis(inputData?.email)
204
+ };
205
+ }
206
+ ;
207
+ static generateEmailDataAnalysis(email) {
208
+ return {
209
+ valid: this.validateEmail(email),
210
+ fraud: false,
211
+ proxiedEmail: false,
212
+ freeSubdomain: false,
213
+ corporate: false,
214
+ email: email || "",
215
+ realUser: "",
216
+ didYouMean: null,
217
+ noReply: false,
218
+ customTLD: false,
219
+ domain: "",
220
+ roleAccount: false,
221
+ plugins: {
222
+ mxRecords: [],
223
+ blocklist: false,
224
+ compromiseDetector: false,
225
+ nsfw: false,
226
+ reputation: "unknown",
227
+ riskScore: 0,
228
+ torNetwork: false,
229
+ typosquatting: 0,
230
+ urlShortener: false
231
+ }
232
+ };
233
+ }
234
+ ;
235
+ static generateIPValidatorResponse(inputData) {
236
+ return {
237
+ ip: inputData?.ip || "",
238
+ allow: this.validateIP(inputData?.ip),
239
+ reasons: this.validateIP(inputData?.ip) ? [] : ["INVALID"],
240
+ response: this.generateIPDataAnalysis(inputData?.ip)
241
+ };
242
+ }
243
+ ;
244
+ static generateIPDataAnalysis(ip) {
245
+ const isValid = this.validateIP(ip);
246
+ return {
247
+ valid: isValid,
248
+ type: isValid ? "IPv4" : "Invalid",
249
+ class: isValid ? "A" : "Unknown",
250
+ fraud: false,
251
+ ip: ip || "",
252
+ continent: "",
253
+ continentCode: "",
254
+ country: "",
255
+ countryCode: "",
256
+ region: "",
257
+ regionName: "",
258
+ city: "",
259
+ district: "",
260
+ zipCode: "",
261
+ lat: 0,
262
+ lon: 0,
263
+ timezone: "",
264
+ offset: 0,
265
+ currency: "",
266
+ isp: "",
267
+ org: "",
268
+ as: "",
269
+ asname: "",
270
+ mobile: false,
271
+ proxy: true,
272
+ hosting: false,
273
+ plugins: {
274
+ blocklist: false,
275
+ riskScore: 0
276
+ }
277
+ };
278
+ }
279
+ ;
280
+ static generatePhoneValidatorResponse(inputData) {
281
+ return {
282
+ phone: inputData?.phone || "",
283
+ allow: this.validatePhone(inputData?.phone),
284
+ reasons: this.validatePhone(inputData?.phone) ? [] : ["INVALID"],
285
+ response: this.generatePhoneDataAnalysis(inputData?.phone)
286
+ };
287
+ }
288
+ ;
289
+ static generatePhoneDataAnalysis(phone) {
290
+ const phoneNumber = phone?.phone || phone;
291
+ const isValid = this.validatePhone(phoneNumber);
292
+ return {
293
+ valid: isValid,
294
+ fraud: false,
295
+ phone: phone?.phone || "",
296
+ prefix: "",
297
+ number: "",
298
+ lineType: "Unknown",
299
+ carrierInfo: {
300
+ carrierName: "",
301
+ accuracy: 0,
302
+ carrierCountry: "",
303
+ carrierCountryCode: ""
304
+ },
305
+ country: "",
306
+ countryCode: "",
307
+ plugins: {
308
+ blocklist: false,
309
+ riskScore: 0
310
+ }
311
+ };
312
+ }
313
+ ;
314
+ static generateHTTPRequest(inputData) {
315
+ return {
316
+ method: inputData?.method || "GET",
317
+ url: inputData?.url || "",
318
+ headers: inputData?.headers || {},
319
+ body: inputData?.body || null,
320
+ allow: false,
321
+ reasons: ["FRAUD"],
322
+ protected: true
323
+ };
324
+ }
325
+ ;
326
+ static generateEmailStatus() {
327
+ return {
328
+ status: false,
329
+ error: "API unavailable - using fallback response"
330
+ };
331
+ }
332
+ ;
333
+ static generateSRNSummary(inputData) {
334
+ const quantity = inputData?.quantity || 1;
335
+ const values = Array.from({ length: quantity }, () => ({
336
+ integer: 0,
337
+ float: 0.0
338
+ }));
339
+ return {
340
+ values,
341
+ executionTime: 0
342
+ };
343
+ }
344
+ ;
345
+ static generateExtractWithTextly(inputData) {
346
+ return {
347
+ data: inputData?.data || "",
348
+ extracted: {},
349
+ error: "API unavailable - using fallback response"
350
+ };
351
+ }
352
+ ;
353
+ static generatePrayerTimes(inputData) {
354
+ return {
355
+ error: "API unavailable - using fallback response"
356
+ };
357
+ }
358
+ ;
359
+ static generateSatinizedInputAnalysis(inputData) {
360
+ return {
361
+ input: inputData?.input || "",
362
+ formats: {
363
+ ascii: false,
364
+ bitcoinAddress: false,
365
+ cLikeIdentifier: false,
366
+ coordinates: false,
367
+ crediCard: false,
368
+ date: false,
369
+ discordUsername: false,
370
+ doi: false,
371
+ domain: false,
372
+ e164Phone: false,
373
+ email: false,
374
+ emoji: false,
375
+ hanUnification: false,
376
+ hashtag: false,
377
+ hyphenWordBreak: false,
378
+ ipv6: false,
379
+ ip: false,
380
+ jiraTicket: false,
381
+ macAddress: false,
382
+ name: false,
383
+ number: false,
384
+ panFromGstin: false,
385
+ password: false,
386
+ port: false,
387
+ tel: false,
388
+ text: false,
389
+ semver: false,
390
+ ssn: false,
391
+ uuid: false,
392
+ url: false,
393
+ urlSlug: false,
394
+ username: false
395
+ },
396
+ includes: {
397
+ spaces: false,
398
+ hasSql: false,
399
+ hasNoSql: false,
400
+ letters: false,
401
+ uppercase: false,
402
+ lowercase: false,
403
+ symbols: false,
404
+ digits: false
405
+ }
406
+ };
407
+ }
408
+ ;
409
+ static generatePasswordValidationResult(inputData) {
410
+ return {
411
+ valid: false,
412
+ password: inputData?.password || "",
413
+ details: [
414
+ {
415
+ validation: "length",
416
+ message: "API unavailable - using fallback response"
417
+ }
418
+ ]
419
+ };
420
+ }
421
+ ;
422
+ }
423
+ ;