@dealcrawl/sdk 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +540 -0
  2. package/dist/sdk/src/client.d.ts +285 -0
  3. package/dist/sdk/src/client.d.ts.map +1 -0
  4. package/dist/sdk/src/client.js +336 -0
  5. package/dist/sdk/src/client.js.map +1 -0
  6. package/dist/sdk/src/error.d.ts +54 -0
  7. package/dist/sdk/src/error.d.ts.map +1 -0
  8. package/dist/sdk/src/error.js +115 -0
  9. package/dist/sdk/src/error.js.map +1 -0
  10. package/dist/sdk/src/index.d.ts +58 -0
  11. package/dist/sdk/src/index.d.ts.map +1 -0
  12. package/dist/sdk/src/index.js +65 -0
  13. package/dist/sdk/src/index.js.map +1 -0
  14. package/dist/sdk/src/resources/account.d.ts +143 -0
  15. package/dist/sdk/src/resources/account.d.ts.map +1 -0
  16. package/dist/sdk/src/resources/account.js +186 -0
  17. package/dist/sdk/src/resources/account.js.map +1 -0
  18. package/dist/sdk/src/resources/crawl.d.ts +87 -0
  19. package/dist/sdk/src/resources/crawl.d.ts.map +1 -0
  20. package/dist/sdk/src/resources/crawl.js +205 -0
  21. package/dist/sdk/src/resources/crawl.js.map +1 -0
  22. package/dist/sdk/src/resources/data.d.ts +157 -0
  23. package/dist/sdk/src/resources/data.d.ts.map +1 -0
  24. package/dist/sdk/src/resources/data.js +239 -0
  25. package/dist/sdk/src/resources/data.js.map +1 -0
  26. package/dist/sdk/src/resources/dork.d.ts +104 -0
  27. package/dist/sdk/src/resources/dork.d.ts.map +1 -0
  28. package/dist/sdk/src/resources/dork.js +163 -0
  29. package/dist/sdk/src/resources/dork.js.map +1 -0
  30. package/dist/sdk/src/resources/extract.d.ts +105 -0
  31. package/dist/sdk/src/resources/extract.d.ts.map +1 -0
  32. package/dist/sdk/src/resources/extract.js +246 -0
  33. package/dist/sdk/src/resources/extract.js.map +1 -0
  34. package/dist/sdk/src/resources/index.d.ts +14 -0
  35. package/dist/sdk/src/resources/index.d.ts.map +1 -0
  36. package/dist/sdk/src/resources/index.js +14 -0
  37. package/dist/sdk/src/resources/index.js.map +1 -0
  38. package/dist/sdk/src/resources/keys.d.ts +124 -0
  39. package/dist/sdk/src/resources/keys.d.ts.map +1 -0
  40. package/dist/sdk/src/resources/keys.js +168 -0
  41. package/dist/sdk/src/resources/keys.js.map +1 -0
  42. package/dist/sdk/src/resources/scrape.d.ts +53 -0
  43. package/dist/sdk/src/resources/scrape.d.ts.map +1 -0
  44. package/dist/sdk/src/resources/scrape.js +85 -0
  45. package/dist/sdk/src/resources/scrape.js.map +1 -0
  46. package/dist/sdk/src/resources/status.d.ts +100 -0
  47. package/dist/sdk/src/resources/status.d.ts.map +1 -0
  48. package/dist/sdk/src/resources/status.js +133 -0
  49. package/dist/sdk/src/resources/status.js.map +1 -0
  50. package/dist/sdk/src/resources/webhooks.d.ts +126 -0
  51. package/dist/sdk/src/resources/webhooks.d.ts.map +1 -0
  52. package/dist/sdk/src/resources/webhooks.js +167 -0
  53. package/dist/sdk/src/resources/webhooks.js.map +1 -0
  54. package/dist/sdk/src/types/config.d.ts +45 -0
  55. package/dist/sdk/src/types/config.d.ts.map +1 -0
  56. package/dist/sdk/src/types/config.js +10 -0
  57. package/dist/sdk/src/types/config.js.map +1 -0
  58. package/dist/sdk/src/types/index.d.ts +8 -0
  59. package/dist/sdk/src/types/index.d.ts.map +1 -0
  60. package/dist/sdk/src/types/index.js +8 -0
  61. package/dist/sdk/src/types/index.js.map +1 -0
  62. package/dist/sdk/src/types/options.d.ts +286 -0
  63. package/dist/sdk/src/types/options.d.ts.map +1 -0
  64. package/dist/sdk/src/types/options.js +6 -0
  65. package/dist/sdk/src/types/options.js.map +1 -0
  66. package/dist/sdk/src/types/responses.d.ts +385 -0
  67. package/dist/sdk/src/types/responses.d.ts.map +1 -0
  68. package/dist/sdk/src/types/responses.js +6 -0
  69. package/dist/sdk/src/types/responses.js.map +1 -0
  70. package/dist/sdk/src/utils/polling.d.ts +57 -0
  71. package/dist/sdk/src/utils/polling.d.ts.map +1 -0
  72. package/dist/sdk/src/utils/polling.js +110 -0
  73. package/dist/sdk/src/utils/polling.js.map +1 -0
  74. package/dist/sdk/src/utils/request.d.ts +47 -0
  75. package/dist/sdk/src/utils/request.d.ts.map +1 -0
  76. package/dist/sdk/src/utils/request.js +161 -0
  77. package/dist/sdk/src/utils/request.js.map +1 -0
  78. package/dist/shared/src/constants/errors.d.ts +26 -0
  79. package/dist/shared/src/constants/errors.d.ts.map +1 -0
  80. package/dist/shared/src/constants/errors.js +39 -0
  81. package/dist/shared/src/constants/errors.js.map +1 -0
  82. package/dist/shared/src/constants/http.d.ts +26 -0
  83. package/dist/shared/src/constants/http.d.ts.map +1 -0
  84. package/dist/shared/src/constants/http.js +26 -0
  85. package/dist/shared/src/constants/http.js.map +1 -0
  86. package/dist/shared/src/constants/index.d.ts +4 -0
  87. package/dist/shared/src/constants/index.d.ts.map +1 -0
  88. package/dist/shared/src/constants/index.js +5 -0
  89. package/dist/shared/src/constants/index.js.map +1 -0
  90. package/dist/shared/src/constants/limits.d.ts +52 -0
  91. package/dist/shared/src/constants/limits.d.ts.map +1 -0
  92. package/dist/shared/src/constants/limits.js +43 -0
  93. package/dist/shared/src/constants/limits.js.map +1 -0
  94. package/dist/shared/src/index.d.ts +5 -0
  95. package/dist/shared/src/index.d.ts.map +1 -0
  96. package/dist/shared/src/index.js +11 -0
  97. package/dist/shared/src/index.js.map +1 -0
  98. package/dist/shared/src/lib/index.d.ts +2 -0
  99. package/dist/shared/src/lib/index.d.ts.map +1 -0
  100. package/dist/shared/src/lib/index.js +2 -0
  101. package/dist/shared/src/lib/index.js.map +1 -0
  102. package/dist/shared/src/lib/redis.d.ts +14 -0
  103. package/dist/shared/src/lib/redis.d.ts.map +1 -0
  104. package/dist/shared/src/lib/redis.js +60 -0
  105. package/dist/shared/src/lib/redis.js.map +1 -0
  106. package/dist/shared/src/types/api-key.types.d.ts +94 -0
  107. package/dist/shared/src/types/api-key.types.d.ts.map +1 -0
  108. package/dist/shared/src/types/api-key.types.js +30 -0
  109. package/dist/shared/src/types/api-key.types.js.map +1 -0
  110. package/dist/shared/src/types/api.types.d.ts +38 -0
  111. package/dist/shared/src/types/api.types.d.ts.map +1 -0
  112. package/dist/shared/src/types/api.types.js +2 -0
  113. package/dist/shared/src/types/api.types.js.map +1 -0
  114. package/dist/shared/src/types/client.types.d.ts +73 -0
  115. package/dist/shared/src/types/client.types.d.ts.map +1 -0
  116. package/dist/shared/src/types/client.types.js +9 -0
  117. package/dist/shared/src/types/client.types.js.map +1 -0
  118. package/dist/shared/src/types/crawl.types.d.ts +65 -0
  119. package/dist/shared/src/types/crawl.types.d.ts.map +1 -0
  120. package/dist/shared/src/types/crawl.types.js +2 -0
  121. package/dist/shared/src/types/crawl.types.js.map +1 -0
  122. package/dist/shared/src/types/deal.types.d.ts +210 -0
  123. package/dist/shared/src/types/deal.types.d.ts.map +1 -0
  124. package/dist/shared/src/types/deal.types.js +6 -0
  125. package/dist/shared/src/types/deal.types.js.map +1 -0
  126. package/dist/shared/src/types/dork.types.d.ts +29 -0
  127. package/dist/shared/src/types/dork.types.d.ts.map +1 -0
  128. package/dist/shared/src/types/dork.types.js +2 -0
  129. package/dist/shared/src/types/dork.types.js.map +1 -0
  130. package/dist/shared/src/types/index.d.ts +8 -0
  131. package/dist/shared/src/types/index.d.ts.map +1 -0
  132. package/dist/shared/src/types/index.js +9 -0
  133. package/dist/shared/src/types/index.js.map +1 -0
  134. package/dist/shared/src/types/scrape.types.d.ts +151 -0
  135. package/dist/shared/src/types/scrape.types.d.ts.map +1 -0
  136. package/dist/shared/src/types/scrape.types.js +2 -0
  137. package/dist/shared/src/types/scrape.types.js.map +1 -0
  138. package/dist/shared/src/utils/date.d.ts +7 -0
  139. package/dist/shared/src/utils/date.d.ts.map +1 -0
  140. package/dist/shared/src/utils/date.js +25 -0
  141. package/dist/shared/src/utils/date.js.map +1 -0
  142. package/dist/shared/src/utils/hash.d.ts +4 -0
  143. package/dist/shared/src/utils/hash.d.ts.map +1 -0
  144. package/dist/shared/src/utils/hash.js +21 -0
  145. package/dist/shared/src/utils/hash.js.map +1 -0
  146. package/dist/shared/src/utils/index.d.ts +7 -0
  147. package/dist/shared/src/utils/index.d.ts.map +1 -0
  148. package/dist/shared/src/utils/index.js +8 -0
  149. package/dist/shared/src/utils/index.js.map +1 -0
  150. package/dist/shared/src/utils/logger.d.ts +66 -0
  151. package/dist/shared/src/utils/logger.d.ts.map +1 -0
  152. package/dist/shared/src/utils/logger.js +268 -0
  153. package/dist/shared/src/utils/logger.js.map +1 -0
  154. package/dist/shared/src/utils/retry.d.ts +11 -0
  155. package/dist/shared/src/utils/retry.d.ts.map +1 -0
  156. package/dist/shared/src/utils/retry.js +36 -0
  157. package/dist/shared/src/utils/retry.js.map +1 -0
  158. package/dist/shared/src/utils/url-validator.d.ts +37 -0
  159. package/dist/shared/src/utils/url-validator.d.ts.map +1 -0
  160. package/dist/shared/src/utils/url-validator.js +179 -0
  161. package/dist/shared/src/utils/url-validator.js.map +1 -0
  162. package/dist/shared/src/utils/url.d.ts +6 -0
  163. package/dist/shared/src/utils/url.d.ts.map +1 -0
  164. package/dist/shared/src/utils/url.js +56 -0
  165. package/dist/shared/src/utils/url.js.map +1 -0
  166. package/package.json +49 -0
@@ -0,0 +1,36 @@
1
+ const defaultOptions = {
2
+ maxRetries: 3,
3
+ initialDelayMs: 1000,
4
+ maxDelayMs: 30000,
5
+ backoffMultiplier: 2,
6
+ shouldRetry: () => true,
7
+ };
8
+ export async function retry(fn, options) {
9
+ const opts = { ...defaultOptions, ...options };
10
+ let lastError = null;
11
+ let delay = opts.initialDelayMs;
12
+ for (let attempt = 1; attempt <= opts.maxRetries; attempt++) {
13
+ try {
14
+ return await fn();
15
+ }
16
+ catch (error) {
17
+ lastError = error instanceof Error ? error : new Error(String(error));
18
+ if (attempt === opts.maxRetries || !opts.shouldRetry(lastError, attempt)) {
19
+ throw lastError;
20
+ }
21
+ await sleep(delay);
22
+ delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelayMs);
23
+ }
24
+ }
25
+ throw lastError;
26
+ }
27
+ export function sleep(ms) {
28
+ return new Promise((resolve) => setTimeout(resolve, ms));
29
+ }
30
+ export async function withTimeout(promise, timeoutMs) {
31
+ const timeout = new Promise((_, reject) => {
32
+ setTimeout(() => reject(new Error("Operation timed out")), timeoutMs);
33
+ });
34
+ return Promise.race([promise, timeout]);
35
+ }
36
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../../../../shared/src/utils/retry.ts"],"names":[],"mappings":"AAQA,MAAM,cAAc,GAA2B;IAC7C,UAAU,EAAE,CAAC;IACb,cAAc,EAAE,IAAI;IACpB,UAAU,EAAE,KAAK;IACjB,iBAAiB,EAAE,CAAC;IACpB,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI;CACxB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,EAAoB,EACpB,OAAsB;IAEtB,MAAM,IAAI,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,EAAE,CAAC;IAC/C,IAAI,SAAS,GAAiB,IAAI,CAAC;IACnC,IAAI,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC;IAEhC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QAC5D,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtE,IAAI,OAAO,KAAK,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;gBACzE,MAAM,SAAS,CAAC;YAClB,CAAC;YAED,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACnB,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAmB,EACnB,SAAiB;IAEjB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * URL Validator with SSRF Protection
3
+ *
4
+ * Prevents Server-Side Request Forgery (SSRF) attacks by blocking:
5
+ * - Private IP ranges (127.0.0.1, 192.168.x.x, 10.x.x.x, etc.)
6
+ * - Local/Link-local addresses
7
+ * - File:// and other dangerous protocols
8
+ * - Localhost and internal domains
9
+ */
10
+ export declare class URLValidationError extends Error {
11
+ readonly code: "INVALID_URL" | "BLOCKED_PROTOCOL" | "BLOCKED_HOSTNAME" | "PRIVATE_IP" | "SSRF_RISK";
12
+ constructor(message: string, code: "INVALID_URL" | "BLOCKED_PROTOCOL" | "BLOCKED_HOSTNAME" | "PRIVATE_IP" | "SSRF_RISK");
13
+ }
14
+ /**
15
+ * Validate URL for SSRF protection
16
+ *
17
+ * @throws {URLValidationError} If URL is invalid or poses SSRF risk
18
+ */
19
+ export declare function validateURL(urlString: string): URL;
20
+ /**
21
+ * Validate URL and return boolean (no throw)
22
+ */
23
+ export declare function isValidURL(urlString: string): boolean;
24
+ /**
25
+ * Validate multiple URLs
26
+ * @returns Array of validation results
27
+ */
28
+ export declare function validateURLs(urls: string[]): Array<{
29
+ url: string;
30
+ valid: boolean;
31
+ error?: string;
32
+ }>;
33
+ /**
34
+ * Sanitize URL by removing dangerous components
35
+ */
36
+ export declare function sanitizeURL(urlString: string): string | null;
37
+ //# sourceMappingURL=url-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-validator.d.ts","sourceRoot":"","sources":["../../../../../shared/src/utils/url-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4CH,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,IAAI,EAChB,aAAa,GACb,kBAAkB,GAClB,kBAAkB,GAClB,YAAY,GACZ,WAAW;gBANf,OAAO,EAAE,MAAM,EACC,IAAI,EAChB,aAAa,GACb,kBAAkB,GAClB,kBAAkB,GAClB,YAAY,GACZ,WAAW;CAKlB;AAkDD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,CA4DlD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EAAE,GACb,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAaxD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5D"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * URL Validator with SSRF Protection
3
+ *
4
+ * Prevents Server-Side Request Forgery (SSRF) attacks by blocking:
5
+ * - Private IP ranges (127.0.0.1, 192.168.x.x, 10.x.x.x, etc.)
6
+ * - Local/Link-local addresses
7
+ * - File:// and other dangerous protocols
8
+ * - Localhost and internal domains
9
+ */
10
+ // ============================================
11
+ // PRIVATE IP RANGES (RFC 1918 + others)
12
+ // ============================================
13
+ const PRIVATE_IP_PATTERNS = [
14
+ // IPv4 Loopback
15
+ /^127\./,
16
+ // IPv4 Private ranges
17
+ /^10\./,
18
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
19
+ /^192\.168\./,
20
+ // Link-local
21
+ /^169\.254\./,
22
+ // IPv4 Broadcast
23
+ /^255\.255\.255\.255$/,
24
+ // IPv6 Loopback
25
+ /^::1$/,
26
+ /^::ffff:127\./,
27
+ // IPv6 Link-local
28
+ /^fe80:/i,
29
+ // IPv6 Unique local
30
+ /^fc00:/i,
31
+ /^fd00:/i,
32
+ ];
33
+ const BLOCKED_HOSTNAMES = [
34
+ "localhost",
35
+ "0.0.0.0",
36
+ "[::]",
37
+ "[::1]",
38
+ "metadata.google.internal", // GCP metadata
39
+ "169.254.169.254", // AWS/Azure metadata
40
+ ];
41
+ const DANGEROUS_PROTOCOLS = ["file:", "ftp:", "gopher:", "jar:", "data:"];
42
+ const ALLOWED_PROTOCOLS = ["http:", "https:"];
43
+ // ============================================
44
+ // VALIDATION ERROR TYPES
45
+ // ============================================
46
+ export class URLValidationError extends Error {
47
+ code;
48
+ constructor(message, code) {
49
+ super(message);
50
+ this.code = code;
51
+ this.name = "URLValidationError";
52
+ }
53
+ }
54
+ // ============================================
55
+ // VALIDATION FUNCTIONS
56
+ // ============================================
57
+ /**
58
+ * Check if hostname is a private/internal IP
59
+ */
60
+ function isPrivateIP(hostname) {
61
+ // Remove brackets from IPv6
62
+ const cleaned = hostname.replace(/^\[|\]$/g, "");
63
+ for (const pattern of PRIVATE_IP_PATTERNS) {
64
+ if (pattern.test(cleaned)) {
65
+ return true;
66
+ }
67
+ }
68
+ return false;
69
+ }
70
+ /**
71
+ * Check if hostname is blocked
72
+ */
73
+ function isBlockedHostname(hostname) {
74
+ const lower = hostname.toLowerCase();
75
+ // Check exact matches
76
+ if (BLOCKED_HOSTNAMES.includes(lower)) {
77
+ return true;
78
+ }
79
+ // Check if ends with .local (mDNS)
80
+ if (lower.endsWith(".local")) {
81
+ return true;
82
+ }
83
+ // Check if is an internal domain
84
+ if (lower.endsWith(".internal") ||
85
+ lower.endsWith(".localhost") ||
86
+ lower === "localhost") {
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+ /**
92
+ * Validate URL for SSRF protection
93
+ *
94
+ * @throws {URLValidationError} If URL is invalid or poses SSRF risk
95
+ */
96
+ export function validateURL(urlString) {
97
+ // Parse URL
98
+ let url;
99
+ try {
100
+ url = new URL(urlString);
101
+ }
102
+ catch {
103
+ throw new URLValidationError(`Invalid URL format: "${urlString}"`, "INVALID_URL");
104
+ }
105
+ // Check protocol
106
+ if (!ALLOWED_PROTOCOLS.includes(url.protocol)) {
107
+ if (DANGEROUS_PROTOCOLS.includes(url.protocol)) {
108
+ throw new URLValidationError(`Dangerous protocol blocked: ${url.protocol}`, "BLOCKED_PROTOCOL");
109
+ }
110
+ throw new URLValidationError(`Protocol not allowed: ${url.protocol} (only HTTP/HTTPS allowed)`, "BLOCKED_PROTOCOL");
111
+ }
112
+ // Check for blocked hostnames
113
+ if (isBlockedHostname(url.hostname)) {
114
+ throw new URLValidationError(`Access to internal/localhost addresses is blocked: ${url.hostname}`, "BLOCKED_HOSTNAME");
115
+ }
116
+ // Check for private IPs
117
+ if (isPrivateIP(url.hostname)) {
118
+ throw new URLValidationError(`Access to private IP addresses is blocked: ${url.hostname}`, "PRIVATE_IP");
119
+ }
120
+ // Check for suspicious patterns
121
+ // Username/password in URL can be used for SSRF
122
+ if (url.username || url.password) {
123
+ throw new URLValidationError("URLs with credentials are not allowed", "SSRF_RISK");
124
+ }
125
+ // Check for URL redirections via @ symbol
126
+ if (url.href.includes("@")) {
127
+ throw new URLValidationError("URLs with @ symbol are not allowed (potential SSRF via redirect)", "SSRF_RISK");
128
+ }
129
+ return url;
130
+ }
131
+ /**
132
+ * Validate URL and return boolean (no throw)
133
+ */
134
+ export function isValidURL(urlString) {
135
+ try {
136
+ validateURL(urlString);
137
+ return true;
138
+ }
139
+ catch {
140
+ return false;
141
+ }
142
+ }
143
+ /**
144
+ * Validate multiple URLs
145
+ * @returns Array of validation results
146
+ */
147
+ export function validateURLs(urls) {
148
+ return urls.map((url) => {
149
+ try {
150
+ validateURL(url);
151
+ return { url, valid: true };
152
+ }
153
+ catch (error) {
154
+ return {
155
+ url,
156
+ valid: false,
157
+ error: error instanceof Error ? error.message : "Unknown error",
158
+ };
159
+ }
160
+ });
161
+ }
162
+ /**
163
+ * Sanitize URL by removing dangerous components
164
+ */
165
+ export function sanitizeURL(urlString) {
166
+ try {
167
+ const url = new URL(urlString);
168
+ // Force HTTPS for security
169
+ url.protocol = "https:";
170
+ // Remove credentials
171
+ url.username = "";
172
+ url.password = "";
173
+ return url.href;
174
+ }
175
+ catch {
176
+ return null;
177
+ }
178
+ }
179
+ //# sourceMappingURL=url-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-validator.js","sourceRoot":"","sources":["../../../../../shared/src/utils/url-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function normalizeUrl(url: string): string;
2
+ export declare function getDomain(url: string): string;
3
+ export declare function isValidUrl(url: string): boolean;
4
+ export declare function isSameDomain(url1: string, url2: string): boolean;
5
+ export declare function joinUrl(base: string, path: string): string;
6
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../../../../shared/src/utils/url.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA0BhD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM1D"}
@@ -0,0 +1,56 @@
1
+ export function normalizeUrl(url) {
2
+ try {
3
+ const parsed = new URL(url);
4
+ parsed.hash = "";
5
+ // Remove common tracking params
6
+ const trackingParams = [
7
+ "utm_source",
8
+ "utm_medium",
9
+ "utm_campaign",
10
+ "utm_content",
11
+ "utm_term",
12
+ "ref",
13
+ "fbclid",
14
+ "gclid",
15
+ ];
16
+ trackingParams.forEach((param) => parsed.searchParams.delete(param));
17
+ let normalized = parsed.href;
18
+ // Remove trailing slash
19
+ if (normalized.endsWith("/") && parsed.pathname !== "/") {
20
+ normalized = normalized.slice(0, -1);
21
+ }
22
+ return normalized;
23
+ }
24
+ catch {
25
+ return url;
26
+ }
27
+ }
28
+ export function getDomain(url) {
29
+ try {
30
+ return new URL(url).hostname;
31
+ }
32
+ catch {
33
+ return "";
34
+ }
35
+ }
36
+ export function isValidUrl(url) {
37
+ try {
38
+ const parsed = new URL(url);
39
+ return ["http:", "https:"].includes(parsed.protocol);
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ export function isSameDomain(url1, url2) {
46
+ return getDomain(url1) === getDomain(url2);
47
+ }
48
+ export function joinUrl(base, path) {
49
+ try {
50
+ return new URL(path, base).href;
51
+ }
52
+ catch {
53
+ return path;
54
+ }
55
+ }
56
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../../../../shared/src/utils/url.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACjB,gCAAgC;QAChC,MAAM,cAAc,GAAG;YACrB,YAAY;YACZ,YAAY;YACZ,cAAc;YACd,aAAa;YACb,UAAU;YACV,KAAK;YACL,QAAQ;YACR,OAAO;SACR,CAAC;QACF,cAAc,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAErE,IAAI,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;QAC7B,wBAAwB;QACxB,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;YACxD,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,IAAY;IACrD,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,IAAY;IAChD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@dealcrawl/sdk",
3
+ "version": "2.0.0",
4
+ "description": "Official SDK for DealCrawl web scraping and crawling API",
5
+ "author": "DealUp <contact@dealup.cc>",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/DealUp-cc/DealCrawl.git",
10
+ "directory": "packages/sdk"
11
+ },
12
+ "keywords": [
13
+ "dealcrawl",
14
+ "web-scraping",
15
+ "crawler",
16
+ "scraper",
17
+ "deal-finder",
18
+ "api-client",
19
+ "sdk"
20
+ ],
21
+ "main": "./dist/sdk/src/index.js",
22
+ "types": "./dist/sdk/src/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "import": "./dist/sdk/src/index.js",
26
+ "require": "./dist/sdk/src/index.js",
27
+ "types": "./dist/sdk/src/index.d.ts"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "README.md"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "type-check": "tsc --noEmit",
37
+ "clean": "rm -rf dist"
38
+ },
39
+ "dependencies": {
40
+ "@dealcrawl/shared": "workspace:*"
41
+ },
42
+ "devDependencies": {
43
+ "typescript": "^5.7.0"
44
+ },
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ },
48
+ "sideEffects": false
49
+ }