instasave-sdk 1.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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/dist/auth-fast.d.ts +32 -0
  4. package/dist/auth-fast.d.ts.map +1 -0
  5. package/dist/auth-fast.js +505 -0
  6. package/dist/auth-fast.js.map +1 -0
  7. package/dist/auth.d.ts +80 -0
  8. package/dist/auth.d.ts.map +1 -0
  9. package/dist/auth.js +370 -0
  10. package/dist/auth.js.map +1 -0
  11. package/dist/benchmark.d.ts +48 -0
  12. package/dist/benchmark.d.ts.map +1 -0
  13. package/dist/benchmark.js +125 -0
  14. package/dist/benchmark.js.map +1 -0
  15. package/dist/health.d.ts +28 -0
  16. package/dist/health.d.ts.map +1 -0
  17. package/dist/health.js +108 -0
  18. package/dist/health.js.map +1 -0
  19. package/dist/index.d.ts +101 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +492 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/logger.d.ts +22 -0
  24. package/dist/logger.d.ts.map +1 -0
  25. package/dist/logger.js +151 -0
  26. package/dist/logger.js.map +1 -0
  27. package/dist/memory.d.ts +56 -0
  28. package/dist/memory.d.ts.map +1 -0
  29. package/dist/memory.js +144 -0
  30. package/dist/memory.js.map +1 -0
  31. package/dist/metrics.d.ts +19 -0
  32. package/dist/metrics.d.ts.map +1 -0
  33. package/dist/metrics.js +79 -0
  34. package/dist/metrics.js.map +1 -0
  35. package/dist/parallel.d.ts +59 -0
  36. package/dist/parallel.d.ts.map +1 -0
  37. package/dist/parallel.js +202 -0
  38. package/dist/parallel.js.map +1 -0
  39. package/dist/platforms/index.d.ts +7 -0
  40. package/dist/platforms/index.d.ts.map +1 -0
  41. package/dist/platforms/index.js +13 -0
  42. package/dist/platforms/index.js.map +1 -0
  43. package/dist/platforms/instagram.d.ts +6 -0
  44. package/dist/platforms/instagram.d.ts.map +1 -0
  45. package/dist/platforms/instagram.js +189 -0
  46. package/dist/platforms/instagram.js.map +1 -0
  47. package/dist/plugins.d.ts +128 -0
  48. package/dist/plugins.d.ts.map +1 -0
  49. package/dist/plugins.js +107 -0
  50. package/dist/plugins.js.map +1 -0
  51. package/dist/test-integration.d.ts +2 -0
  52. package/dist/test-integration.d.ts.map +1 -0
  53. package/dist/test-integration.js +46 -0
  54. package/dist/test-integration.js.map +1 -0
  55. package/dist/types.d.ts +75 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +6 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/worker.d.ts +2 -0
  60. package/dist/worker.d.ts.map +1 -0
  61. package/dist/worker.js +23 -0
  62. package/dist/worker.js.map +1 -0
  63. package/package.json +56 -0
package/dist/logger.js ADDED
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * Structured Logger with format: TIMESTAMP | LEVEL | module:function:line - message
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.log = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const LEVEL_PRIORITY = {
43
+ DEBUG: 0,
44
+ INFO: 1,
45
+ WARNING: 2,
46
+ ERROR: 3
47
+ };
48
+ class Logger {
49
+ constructor() {
50
+ this.logFile = null;
51
+ this.minLevel = 'DEBUG';
52
+ this.initLogFile();
53
+ this.minLevel = process.env.LOG_LEVEL || 'DEBUG';
54
+ }
55
+ initLogFile() {
56
+ try {
57
+ const logsDir = path.join(process.cwd(), 'logs');
58
+ if (!fs.existsSync(logsDir)) {
59
+ fs.mkdirSync(logsDir, { recursive: true });
60
+ }
61
+ this.logFile = path.join(logsDir, 'app.log');
62
+ // Rotate if > 10MB
63
+ if (fs.existsSync(this.logFile)) {
64
+ const stats = fs.statSync(this.logFile);
65
+ if (stats.size > 10 * 1024 * 1024) {
66
+ const backup = this.logFile + '.old';
67
+ if (fs.existsSync(backup))
68
+ fs.unlinkSync(backup);
69
+ fs.renameSync(this.logFile, backup);
70
+ }
71
+ }
72
+ }
73
+ catch {
74
+ this.logFile = null;
75
+ }
76
+ }
77
+ getCallerInfo() {
78
+ const err = new Error();
79
+ const stack = err.stack?.split('\n') || [];
80
+ // Find first stack frame outside logger.ts
81
+ for (let i = 3; i < stack.length; i++) {
82
+ const line = stack[i];
83
+ if (line.includes('logger.ts') || line.includes('logger.js'))
84
+ continue;
85
+ // Parse: "at functionName (file:line:col)" or "at file:line:col"
86
+ const match = line.match(/at\s+(?:(.+?)\s+\()?(?:.*[/\\])?([^/\\]+?):(\d+):\d+\)?/);
87
+ if (match) {
88
+ const func = match[1]?.replace(/^Object\./, '') || 'anonymous';
89
+ const file = match[2]?.replace(/\.[jt]s$/, '') || 'unknown';
90
+ const lineNum = match[3] || '?';
91
+ return `${file}:${func}:${lineNum}`;
92
+ }
93
+ }
94
+ return 'unknown:unknown:?';
95
+ }
96
+ formatTimestamp() {
97
+ const now = new Date();
98
+ return now.toISOString().replace('T', ' ').substring(0, 19);
99
+ }
100
+ formatMessage(level, message, ...args) {
101
+ const timestamp = this.formatTimestamp();
102
+ const caller = this.getCallerInfo();
103
+ const levelPadded = level.padEnd(8);
104
+ // Format args
105
+ const formattedArgs = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
106
+ const fullMessage = formattedArgs ? `${message} ${formattedArgs}` : message;
107
+ return `${timestamp} | ${levelPadded} | ${caller} - ${fullMessage}`;
108
+ }
109
+ shouldLog(level) {
110
+ return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[this.minLevel];
111
+ }
112
+ writeToFile(formatted) {
113
+ if (this.logFile) {
114
+ try {
115
+ fs.appendFileSync(this.logFile, formatted + '\n');
116
+ }
117
+ catch { }
118
+ }
119
+ }
120
+ log(level, message, ...args) {
121
+ if (!this.shouldLog(level))
122
+ return;
123
+ const formatted = this.formatMessage(level, message, ...args);
124
+ this.writeToFile(formatted);
125
+ switch (level) {
126
+ case 'ERROR':
127
+ console.error(formatted);
128
+ break;
129
+ case 'WARNING':
130
+ console.warn(formatted);
131
+ break;
132
+ default:
133
+ console.log(formatted);
134
+ }
135
+ }
136
+ debug(message, ...args) {
137
+ this.log('DEBUG', message, ...args);
138
+ }
139
+ info(message, ...args) {
140
+ this.log('INFO', message, ...args);
141
+ }
142
+ warn(message, ...args) {
143
+ this.log('WARNING', message, ...args);
144
+ }
145
+ error(message, ...args) {
146
+ this.log('ERROR', message, ...args);
147
+ }
148
+ }
149
+ exports.log = new Logger();
150
+ exports.default = exports.log;
151
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ interface MemoryLeak {
2
+ detected: boolean;
3
+ severity: 'low' | 'medium' | 'high';
4
+ growthRate: number;
5
+ recommendation: string;
6
+ }
7
+ /**
8
+ * Monitors memory usage and detects potential memory leaks
9
+ * @class MemoryMonitor
10
+ */
11
+ export declare class MemoryMonitor {
12
+ private snapshots;
13
+ private monitoringInterval;
14
+ private readonly maxSnapshots;
15
+ private readonly leakThreshold;
16
+ /**
17
+ * Starts memory monitoring
18
+ * @param intervalMs - Monitoring interval in milliseconds (default: 5000)
19
+ */
20
+ startMonitoring(intervalMs?: number): void;
21
+ /**
22
+ * Stops memory monitoring
23
+ */
24
+ stopMonitoring(): void;
25
+ /**
26
+ * Takes a memory usage snapshot
27
+ */
28
+ takeSnapshot(): void;
29
+ /**
30
+ * Analyzes memory usage for potential leaks
31
+ * @returns MemoryLeak analysis result
32
+ */
33
+ detectLeaks(): MemoryLeak;
34
+ /**
35
+ * Gets current memory statistics
36
+ */
37
+ getMemoryStats(): {
38
+ current: {
39
+ heapUsed: string;
40
+ heapTotal: string;
41
+ rss: string;
42
+ };
43
+ leak: MemoryLeak;
44
+ snapshotCount: number;
45
+ } | null;
46
+ /**
47
+ * Forces garbage collection (if --expose-gc flag is used)
48
+ */
49
+ forceGC(): boolean;
50
+ /**
51
+ * Clears all snapshots
52
+ */
53
+ clearSnapshots(): void;
54
+ }
55
+ export {};
56
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AASA,UAAU,UAAU;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,kBAAkB,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAO;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoB;IAElD;;;OAGG;IACH,eAAe,CAAC,UAAU,GAAE,MAAa,GAAG,IAAI;IAYhD;;OAEG;IACH,cAAc,IAAI,IAAI;IAQtB;;OAEG;IACH,YAAY,IAAI,IAAI;IAkBpB;;;OAGG;IACH,WAAW,IAAI,UAAU;IA8CzB;;OAEG;IACH,cAAc;;;;;;;;;IAmBd;;OAEG;IACH,OAAO,IAAI,OAAO;IAWlB;;OAEG;IACH,cAAc,IAAI,IAAI;CAIvB"}
package/dist/memory.js ADDED
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryMonitor = void 0;
4
+ const logger_1 = require("./logger");
5
+ /**
6
+ * Monitors memory usage and detects potential memory leaks
7
+ * @class MemoryMonitor
8
+ */
9
+ class MemoryMonitor {
10
+ constructor() {
11
+ this.snapshots = [];
12
+ this.monitoringInterval = null;
13
+ this.maxSnapshots = 100;
14
+ this.leakThreshold = 10 * 1024 * 1024; // 10MB growth
15
+ }
16
+ /**
17
+ * Starts memory monitoring
18
+ * @param intervalMs - Monitoring interval in milliseconds (default: 5000)
19
+ */
20
+ startMonitoring(intervalMs = 5000) {
21
+ if (this.monitoringInterval) {
22
+ this.stopMonitoring();
23
+ }
24
+ this.monitoringInterval = setInterval(() => {
25
+ this.takeSnapshot();
26
+ }, intervalMs);
27
+ logger_1.log.info(`🔍 Memory monitoring started (interval: ${intervalMs}ms)`);
28
+ }
29
+ /**
30
+ * Stops memory monitoring
31
+ */
32
+ stopMonitoring() {
33
+ if (this.monitoringInterval) {
34
+ clearInterval(this.monitoringInterval);
35
+ this.monitoringInterval = null;
36
+ logger_1.log.info('🛑 Memory monitoring stopped');
37
+ }
38
+ }
39
+ /**
40
+ * Takes a memory usage snapshot
41
+ */
42
+ takeSnapshot() {
43
+ const memoryUsage = process.memoryUsage();
44
+ const snapshot = {
45
+ timestamp: Date.now(),
46
+ heapUsed: memoryUsage.heapUsed,
47
+ heapTotal: memoryUsage.heapTotal,
48
+ external: memoryUsage.external,
49
+ rss: memoryUsage.rss
50
+ };
51
+ this.snapshots.push(snapshot);
52
+ // Keep only recent snapshots
53
+ if (this.snapshots.length > this.maxSnapshots) {
54
+ this.snapshots.shift();
55
+ }
56
+ }
57
+ /**
58
+ * Analyzes memory usage for potential leaks
59
+ * @returns MemoryLeak analysis result
60
+ */
61
+ detectLeaks() {
62
+ if (this.snapshots.length < 10) {
63
+ return {
64
+ detected: false,
65
+ severity: 'low',
66
+ growthRate: 0,
67
+ recommendation: 'Not enough data for analysis'
68
+ };
69
+ }
70
+ // Calculate memory growth rate
71
+ const recent = this.snapshots.slice(-10);
72
+ const oldest = recent[0];
73
+ const newest = recent[recent.length - 1];
74
+ const timeDiff = newest.timestamp - oldest.timestamp;
75
+ const memoryDiff = newest.heapUsed - oldest.heapUsed;
76
+ const growthRate = (memoryDiff / timeDiff) * 1000; // bytes per second
77
+ let detected = false;
78
+ let severity = 'low';
79
+ let recommendation = 'Memory usage is stable';
80
+ if (memoryDiff > this.leakThreshold) {
81
+ detected = true;
82
+ if (growthRate > 1024 * 1024) { // 1MB/s
83
+ severity = 'high';
84
+ recommendation = 'Critical: High memory growth detected. Check for unclosed resources.';
85
+ }
86
+ else if (growthRate > 512 * 1024) { // 512KB/s
87
+ severity = 'medium';
88
+ recommendation = 'Warning: Moderate memory growth detected. Monitor closely.';
89
+ }
90
+ else {
91
+ severity = 'low';
92
+ recommendation = 'Info: Slow memory growth detected. May be normal operation.';
93
+ }
94
+ }
95
+ return {
96
+ detected,
97
+ severity,
98
+ growthRate,
99
+ recommendation
100
+ };
101
+ }
102
+ /**
103
+ * Gets current memory statistics
104
+ */
105
+ getMemoryStats() {
106
+ if (this.snapshots.length === 0) {
107
+ return null;
108
+ }
109
+ const latest = this.snapshots[this.snapshots.length - 1];
110
+ const leak = this.detectLeaks();
111
+ return {
112
+ current: {
113
+ heapUsed: (latest.heapUsed / 1024 / 1024).toFixed(2) + ' MB',
114
+ heapTotal: (latest.heapTotal / 1024 / 1024).toFixed(2) + ' MB',
115
+ rss: (latest.rss / 1024 / 1024).toFixed(2) + ' MB'
116
+ },
117
+ leak,
118
+ snapshotCount: this.snapshots.length
119
+ };
120
+ }
121
+ /**
122
+ * Forces garbage collection (if --expose-gc flag is used)
123
+ */
124
+ forceGC() {
125
+ if (global.gc) {
126
+ global.gc();
127
+ logger_1.log.info('🗑️ Garbage collection forced');
128
+ return true;
129
+ }
130
+ else {
131
+ logger_1.log.info('⚠️ Garbage collection not available. Run with --expose-gc flag.');
132
+ return false;
133
+ }
134
+ }
135
+ /**
136
+ * Clears all snapshots
137
+ */
138
+ clearSnapshots() {
139
+ this.snapshots = [];
140
+ logger_1.log.info('🧹 Memory snapshots cleared');
141
+ }
142
+ }
143
+ exports.MemoryMonitor = MemoryMonitor;
144
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface ScrapingMetrics {
2
+ totalRequests: number;
3
+ successfulRequests: number;
4
+ failedRequests: number;
5
+ averageResponseTime: number;
6
+ totalImagesExtracted: number;
7
+ totalDataSize: number;
8
+ errorsByType: Record<string, number>;
9
+ requestsByHour: Record<string, number>;
10
+ }
11
+ export declare class MetricsCollector {
12
+ private metrics;
13
+ private responseTimes;
14
+ recordRequest(success: boolean, responseTime: number, imageCount?: number, dataSize?: number, error?: string): void;
15
+ getMetrics(): ScrapingMetrics;
16
+ getPrometheusMetrics(): string;
17
+ reset(): void;
18
+ }
19
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CASb;IAEF,OAAO,CAAC,aAAa,CAAgB;IAErC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAU,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAuBzH,UAAU,IAAI,eAAe;IAI7B,oBAAoB,IAAI,MAAM;IAwB9B,KAAK,IAAI,IAAI;CAad"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MetricsCollector = void 0;
4
+ class MetricsCollector {
5
+ constructor() {
6
+ this.metrics = {
7
+ totalRequests: 0,
8
+ successfulRequests: 0,
9
+ failedRequests: 0,
10
+ averageResponseTime: 0,
11
+ totalImagesExtracted: 0,
12
+ totalDataSize: 0,
13
+ errorsByType: {},
14
+ requestsByHour: {}
15
+ };
16
+ this.responseTimes = [];
17
+ }
18
+ recordRequest(success, responseTime, imageCount = 0, dataSize = 0, error) {
19
+ this.metrics.totalRequests++;
20
+ this.responseTimes.push(responseTime);
21
+ if (success) {
22
+ this.metrics.successfulRequests++;
23
+ this.metrics.totalImagesExtracted += imageCount;
24
+ this.metrics.totalDataSize += dataSize;
25
+ }
26
+ else {
27
+ this.metrics.failedRequests++;
28
+ if (error) {
29
+ this.metrics.errorsByType[error] = (this.metrics.errorsByType[error] || 0) + 1;
30
+ }
31
+ }
32
+ // Update average response time
33
+ this.metrics.averageResponseTime = this.responseTimes.reduce((a, b) => a + b, 0) / this.responseTimes.length;
34
+ // Track requests by hour
35
+ const hour = new Date().getHours().toString();
36
+ this.metrics.requestsByHour[hour] = (this.metrics.requestsByHour[hour] || 0) + 1;
37
+ }
38
+ getMetrics() {
39
+ return { ...this.metrics };
40
+ }
41
+ getPrometheusMetrics() {
42
+ return `
43
+ # HELP instasave_requests_total Total number of scraping requests
44
+ # TYPE instasave_requests_total counter
45
+ instasave_requests_total ${this.metrics.totalRequests}
46
+
47
+ # HELP instasave_requests_successful_total Successful scraping requests
48
+ # TYPE instasave_requests_successful_total counter
49
+ instasave_requests_successful_total ${this.metrics.successfulRequests}
50
+
51
+ # HELP instasave_requests_failed_total Failed scraping requests
52
+ # TYPE instasave_requests_failed_total counter
53
+ instasave_requests_failed_total ${this.metrics.failedRequests}
54
+
55
+ # HELP instasave_response_time_avg Average response time in milliseconds
56
+ # TYPE instasave_response_time_avg gauge
57
+ instasave_response_time_avg ${this.metrics.averageResponseTime}
58
+
59
+ # HELP instasave_images_extracted_total Total images extracted
60
+ # TYPE instasave_images_extracted_total counter
61
+ instasave_images_extracted_total ${this.metrics.totalImagesExtracted}
62
+ `.trim();
63
+ }
64
+ reset() {
65
+ this.metrics = {
66
+ totalRequests: 0,
67
+ successfulRequests: 0,
68
+ failedRequests: 0,
69
+ averageResponseTime: 0,
70
+ totalImagesExtracted: 0,
71
+ totalDataSize: 0,
72
+ errorsByType: {},
73
+ requestsByHour: {}
74
+ };
75
+ this.responseTimes = [];
76
+ }
77
+ }
78
+ exports.MetricsCollector = MetricsCollector;
79
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":";;;AAYA,MAAa,gBAAgB;IAA7B;QACU,YAAO,GAAoB;YACjC,aAAa,EAAE,CAAC;YAChB,kBAAkB,EAAE,CAAC;YACrB,cAAc,EAAE,CAAC;YACjB,mBAAmB,EAAE,CAAC;YACtB,oBAAoB,EAAE,CAAC;YACvB,aAAa,EAAE,CAAC;YAChB,YAAY,EAAE,EAAE;YAChB,cAAc,EAAE,EAAE;SACnB,CAAC;QAEM,kBAAa,GAAa,EAAE,CAAC;IAkEvC,CAAC;IAhEC,aAAa,CAAC,OAAgB,EAAE,YAAoB,EAAE,aAAqB,CAAC,EAAE,WAAmB,CAAC,EAAE,KAAc;QAChH,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEtC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,oBAAoB,IAAI,UAAU,CAAC;YAChD,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,QAAQ,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;YAC9B,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAE7G,yBAAyB;QACzB,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACnF,CAAC;IAED,UAAU;QACR,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED,oBAAoB;QAClB,OAAO;;;2BAGgB,IAAI,CAAC,OAAO,CAAC,aAAa;;;;sCAIf,IAAI,CAAC,OAAO,CAAC,kBAAkB;;;;kCAInC,IAAI,CAAC,OAAO,CAAC,cAAc;;;;8BAI/B,IAAI,CAAC,OAAO,CAAC,mBAAmB;;;;mCAI3B,IAAI,CAAC,OAAO,CAAC,oBAAoB;CACnE,CAAC,IAAI,EAAE,CAAC;IACP,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG;YACb,aAAa,EAAE,CAAC;YAChB,kBAAkB,EAAE,CAAC;YACrB,cAAc,EAAE,CAAC;YACjB,mBAAmB,EAAE,CAAC;YACtB,oBAAoB,EAAE,CAAC;YACvB,aAAa,EAAE,CAAC;YAChB,YAAY,EAAE,EAAE;YAChB,cAAc,EAAE,EAAE;SACnB,CAAC;QACF,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;IAC1B,CAAC;CACF;AA9ED,4CA8EC"}
@@ -0,0 +1,59 @@
1
+ import { InstagramPostData, ScrapingOptions } from './index';
2
+ /**
3
+ * Parallel processing manager for Instagram scraping
4
+ * @class ParallelProcessor
5
+ */
6
+ export declare class ParallelProcessor {
7
+ private workerPool;
8
+ private tasks;
9
+ private maxWorkers;
10
+ /**
11
+ * Creates a new ParallelProcessor
12
+ * @param maxWorkers - Maximum number of worker threads (default: 4)
13
+ */
14
+ constructor(maxWorkers?: number);
15
+ /**
16
+ * Initializes the worker thread pool
17
+ */
18
+ private initializeWorkerPool;
19
+ /**
20
+ * Handles messages from worker threads
21
+ */
22
+ private handleWorkerMessage;
23
+ /**
24
+ * Handles worker errors
25
+ */
26
+ private handleWorkerError;
27
+ /**
28
+ * Scrapes multiple Instagram posts in parallel
29
+ * @param urls - Array of Instagram post URLs
30
+ * @param options - Scraping options
31
+ * @returns Promise<InstagramPostData[]>
32
+ */
33
+ scrapeMultiple(urls: string[], options?: ScrapingOptions): Promise<InstagramPostData[]>;
34
+ /**
35
+ * Executes tasks using available workers
36
+ */
37
+ private executeTasks;
38
+ /**
39
+ * Gets processing statistics
40
+ */
41
+ getStats(): {
42
+ totalTasks: number;
43
+ completed: number;
44
+ failed: number;
45
+ running: number;
46
+ pending: number;
47
+ availableWorkers: number;
48
+ busyWorkers: number;
49
+ };
50
+ /**
51
+ * Generates unique task ID
52
+ */
53
+ private generateTaskId;
54
+ /**
55
+ * Shuts down all workers
56
+ */
57
+ shutdown(): Promise<void>;
58
+ }
59
+ //# sourceMappingURL=parallel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAqB7D;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,UAAU,CAAS;IAE3B;;;OAGG;gBACS,UAAU,GAAE,MAAU;IAUlC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAiB5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiBzB;;;;;OAKG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAgCjG;;OAEG;YACW,YAAY;IA2D1B;;OAEG;IACH,QAAQ;;;;;;;;;IAkBR;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAMhC"}