s3db.js 13.6.0 → 14.0.2
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.
- package/README.md +139 -43
- package/dist/s3db.cjs +72425 -38970
- package/dist/s3db.cjs.map +1 -1
- package/dist/s3db.es.js +72177 -38764
- package/dist/s3db.es.js.map +1 -1
- package/mcp/lib/base-handler.js +157 -0
- package/mcp/lib/handlers/connection-handler.js +280 -0
- package/mcp/lib/handlers/query-handler.js +533 -0
- package/mcp/lib/handlers/resource-handler.js +428 -0
- package/mcp/lib/tool-registry.js +336 -0
- package/mcp/lib/tools/connection-tools.js +161 -0
- package/mcp/lib/tools/query-tools.js +267 -0
- package/mcp/lib/tools/resource-tools.js +404 -0
- package/package.json +94 -49
- package/src/clients/memory-client.class.js +346 -191
- package/src/clients/memory-storage.class.js +300 -84
- package/src/clients/s3-client.class.js +7 -6
- package/src/concerns/geo-encoding.js +19 -2
- package/src/concerns/ip.js +59 -9
- package/src/concerns/money.js +8 -1
- package/src/concerns/password-hashing.js +49 -8
- package/src/concerns/plugin-storage.js +186 -18
- package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
- package/src/database.class.js +139 -29
- package/src/errors.js +332 -42
- package/src/plugins/api/auth/oidc-auth.js +66 -17
- package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
- package/src/plugins/api/auth/strategies/factory.class.js +63 -0
- package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
- package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
- package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
- package/src/plugins/api/concerns/failban-manager.js +106 -57
- package/src/plugins/api/concerns/opengraph-helper.js +116 -0
- package/src/plugins/api/concerns/route-context.js +601 -0
- package/src/plugins/api/concerns/state-machine.js +288 -0
- package/src/plugins/api/index.js +180 -41
- package/src/plugins/api/routes/auth-routes.js +198 -30
- package/src/plugins/api/routes/resource-routes.js +19 -4
- package/src/plugins/api/server/health-manager.class.js +163 -0
- package/src/plugins/api/server/middleware-chain.class.js +310 -0
- package/src/plugins/api/server/router.class.js +472 -0
- package/src/plugins/api/server.js +280 -1303
- package/src/plugins/api/utils/custom-routes.js +17 -5
- package/src/plugins/api/utils/guards.js +76 -17
- package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
- package/src/plugins/api/utils/openapi-generator.js +7 -6
- package/src/plugins/api/utils/template-engine.js +77 -3
- package/src/plugins/audit.plugin.js +30 -8
- package/src/plugins/backup.plugin.js +110 -14
- package/src/plugins/cache/cache.class.js +22 -5
- package/src/plugins/cache/filesystem-cache.class.js +116 -19
- package/src/plugins/cache/memory-cache.class.js +211 -57
- package/src/plugins/cache/multi-tier-cache.class.js +371 -0
- package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
- package/src/plugins/cache/redis-cache.class.js +552 -0
- package/src/plugins/cache/s3-cache.class.js +17 -8
- package/src/plugins/cache.plugin.js +176 -61
- package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
- package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
- package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
- package/src/plugins/cloud-inventory/index.js +29 -8
- package/src/plugins/cloud-inventory/registry.js +64 -42
- package/src/plugins/cloud-inventory.plugin.js +240 -138
- package/src/plugins/concerns/plugin-dependencies.js +54 -0
- package/src/plugins/concerns/resource-names.js +100 -0
- package/src/plugins/consumers/index.js +10 -2
- package/src/plugins/consumers/sqs-consumer.js +12 -2
- package/src/plugins/cookie-farm-suite.plugin.js +278 -0
- package/src/plugins/cookie-farm.errors.js +73 -0
- package/src/plugins/cookie-farm.plugin.js +869 -0
- package/src/plugins/costs.plugin.js +7 -1
- package/src/plugins/eventual-consistency/analytics.js +94 -19
- package/src/plugins/eventual-consistency/config.js +15 -7
- package/src/plugins/eventual-consistency/consolidation.js +29 -11
- package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
- package/src/plugins/eventual-consistency/helpers.js +39 -14
- package/src/plugins/eventual-consistency/install.js +21 -2
- package/src/plugins/eventual-consistency/utils.js +32 -10
- package/src/plugins/fulltext.plugin.js +38 -11
- package/src/plugins/geo.plugin.js +61 -9
- package/src/plugins/identity/concerns/config.js +61 -0
- package/src/plugins/identity/concerns/mfa-manager.js +15 -2
- package/src/plugins/identity/concerns/rate-limit.js +124 -0
- package/src/plugins/identity/concerns/resource-schemas.js +9 -1
- package/src/plugins/identity/concerns/token-generator.js +29 -4
- package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
- package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
- package/src/plugins/identity/drivers/index.js +18 -0
- package/src/plugins/identity/drivers/password-driver.js +122 -0
- package/src/plugins/identity/email-service.js +17 -2
- package/src/plugins/identity/index.js +413 -69
- package/src/plugins/identity/oauth2-server.js +413 -30
- package/src/plugins/identity/oidc-discovery.js +16 -8
- package/src/plugins/identity/rsa-keys.js +115 -35
- package/src/plugins/identity/server.js +166 -45
- package/src/plugins/identity/session-manager.js +53 -7
- package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
- package/src/plugins/identity/ui/routes.js +363 -255
- package/src/plugins/importer/index.js +153 -20
- package/src/plugins/index.js +9 -2
- package/src/plugins/kubernetes-inventory/index.js +6 -0
- package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
- package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
- package/src/plugins/kubernetes-inventory.plugin.js +980 -0
- package/src/plugins/metrics.plugin.js +64 -16
- package/src/plugins/ml/base-model.class.js +25 -15
- package/src/plugins/ml/regression-model.class.js +1 -1
- package/src/plugins/ml.errors.js +57 -25
- package/src/plugins/ml.plugin.js +28 -4
- package/src/plugins/namespace.js +210 -0
- package/src/plugins/plugin.class.js +180 -8
- package/src/plugins/puppeteer/console-monitor.js +729 -0
- package/src/plugins/puppeteer/cookie-manager.js +492 -0
- package/src/plugins/puppeteer/network-monitor.js +816 -0
- package/src/plugins/puppeteer/performance-manager.js +746 -0
- package/src/plugins/puppeteer/proxy-manager.js +478 -0
- package/src/plugins/puppeteer/stealth-manager.js +556 -0
- package/src/plugins/puppeteer.errors.js +81 -0
- package/src/plugins/puppeteer.plugin.js +1327 -0
- package/src/plugins/queue-consumer.plugin.js +69 -14
- package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
- package/src/plugins/recon/concerns/command-runner.js +148 -0
- package/src/plugins/recon/concerns/diff-detector.js +372 -0
- package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
- package/src/plugins/recon/concerns/process-manager.js +338 -0
- package/src/plugins/recon/concerns/report-generator.js +478 -0
- package/src/plugins/recon/concerns/security-analyzer.js +571 -0
- package/src/plugins/recon/concerns/target-normalizer.js +68 -0
- package/src/plugins/recon/config/defaults.js +321 -0
- package/src/plugins/recon/config/resources.js +370 -0
- package/src/plugins/recon/index.js +778 -0
- package/src/plugins/recon/managers/dependency-manager.js +174 -0
- package/src/plugins/recon/managers/scheduler-manager.js +179 -0
- package/src/plugins/recon/managers/storage-manager.js +745 -0
- package/src/plugins/recon/managers/target-manager.js +274 -0
- package/src/plugins/recon/stages/asn-stage.js +314 -0
- package/src/plugins/recon/stages/certificate-stage.js +84 -0
- package/src/plugins/recon/stages/dns-stage.js +107 -0
- package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
- package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
- package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
- package/src/plugins/recon/stages/http-stage.js +89 -0
- package/src/plugins/recon/stages/latency-stage.js +148 -0
- package/src/plugins/recon/stages/massdns-stage.js +302 -0
- package/src/plugins/recon/stages/osint-stage.js +1373 -0
- package/src/plugins/recon/stages/ports-stage.js +169 -0
- package/src/plugins/recon/stages/screenshot-stage.js +94 -0
- package/src/plugins/recon/stages/secrets-stage.js +514 -0
- package/src/plugins/recon/stages/subdomains-stage.js +295 -0
- package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
- package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
- package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
- package/src/plugins/recon/stages/whois-stage.js +349 -0
- package/src/plugins/recon.plugin.js +75 -0
- package/src/plugins/recon.plugin.js.backup +2635 -0
- package/src/plugins/relation.errors.js +87 -14
- package/src/plugins/replicator.plugin.js +514 -137
- package/src/plugins/replicators/base-replicator.class.js +89 -1
- package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
- package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mysql-replicator.class.js +52 -17
- package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
- package/src/plugins/replicators/postgres-replicator.class.js +62 -27
- package/src/plugins/replicators/s3db-replicator.class.js +25 -18
- package/src/plugins/replicators/schema-sync.helper.js +3 -3
- package/src/plugins/replicators/sqs-replicator.class.js +8 -2
- package/src/plugins/replicators/turso-replicator.class.js +23 -3
- package/src/plugins/replicators/webhook-replicator.class.js +42 -4
- package/src/plugins/s3-queue.plugin.js +464 -65
- package/src/plugins/scheduler.plugin.js +20 -6
- package/src/plugins/state-machine.plugin.js +40 -9
- package/src/plugins/tfstate/README.md +126 -126
- package/src/plugins/tfstate/base-driver.js +28 -4
- package/src/plugins/tfstate/errors.js +65 -10
- package/src/plugins/tfstate/filesystem-driver.js +52 -8
- package/src/plugins/tfstate/index.js +163 -90
- package/src/plugins/tfstate/s3-driver.js +64 -6
- package/src/plugins/ttl.plugin.js +72 -17
- package/src/plugins/vector/distances.js +18 -12
- package/src/plugins/vector/kmeans.js +26 -4
- package/src/resource.class.js +115 -19
- package/src/testing/factory.class.js +20 -3
- package/src/testing/seeder.class.js +7 -1
- package/src/clients/memory-client.md +0 -917
- package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
|
@@ -0,0 +1,778 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReconPlugin - Modular Refactored Version
|
|
3
|
+
*
|
|
4
|
+
* Main orchestrator that coordinates managers, stages, and concerns.
|
|
5
|
+
* Backward compatible with the original monolithic API.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* - Managers: Handle high-level operations (storage, targets, scheduling, dependencies)
|
|
9
|
+
* - Stages: Execute individual reconnaissance tasks (DNS, ports, subdomains, etc.)
|
|
10
|
+
* - Concerns: Shared utilities (command runner, normalizer, report generator, etc.)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { Plugin } from '../plugin.class.js';
|
|
14
|
+
|
|
15
|
+
// Managers
|
|
16
|
+
import { StorageManager } from './managers/storage-manager.js';
|
|
17
|
+
import { TargetManager } from './managers/target-manager.js';
|
|
18
|
+
import { SchedulerManager } from './managers/scheduler-manager.js';
|
|
19
|
+
import { DependencyManager } from './managers/dependency-manager.js';
|
|
20
|
+
|
|
21
|
+
// Stages
|
|
22
|
+
import { DnsStage } from './stages/dns-stage.js';
|
|
23
|
+
import { CertificateStage } from './stages/certificate-stage.js';
|
|
24
|
+
import { LatencyStage } from './stages/latency-stage.js';
|
|
25
|
+
import { HttpStage } from './stages/http-stage.js';
|
|
26
|
+
import { PortsStage } from './stages/ports-stage.js';
|
|
27
|
+
import { SubdomainsStage } from './stages/subdomains-stage.js';
|
|
28
|
+
import { WebDiscoveryStage } from './stages/web-discovery-stage.js';
|
|
29
|
+
import { VulnerabilityStage } from './stages/vulnerability-stage.js';
|
|
30
|
+
import { TlsAuditStage } from './stages/tls-audit-stage.js';
|
|
31
|
+
import { FingerprintStage } from './stages/fingerprint-stage.js';
|
|
32
|
+
import { ScreenshotStage } from './stages/screenshot-stage.js';
|
|
33
|
+
import { OsintStage } from './stages/osint-stage.js';
|
|
34
|
+
import { WhoisStage } from './stages/whois-stage.js';
|
|
35
|
+
import { SecretsStage } from './stages/secrets-stage.js';
|
|
36
|
+
import { ASNStage } from './stages/asn-stage.js';
|
|
37
|
+
import { DNSDumpsterStage } from './stages/dnsdumpster-stage.js';
|
|
38
|
+
import { MassDNSStage } from './stages/massdns-stage.js';
|
|
39
|
+
import { GoogleDorksStage } from './stages/google-dorks-stage.js';
|
|
40
|
+
|
|
41
|
+
// Concerns
|
|
42
|
+
import { CommandRunner } from './concerns/command-runner.js';
|
|
43
|
+
import { TargetNormalizer } from './concerns/target-normalizer.js';
|
|
44
|
+
import { FingerprintBuilder } from './concerns/fingerprint-builder.js';
|
|
45
|
+
import { ReportGenerator } from './concerns/report-generator.js';
|
|
46
|
+
import { DiffDetector } from './concerns/diff-detector.js';
|
|
47
|
+
import { SecurityAnalyzer } from './concerns/security-analyzer.js';
|
|
48
|
+
import { processManager } from './concerns/process-manager.js';
|
|
49
|
+
|
|
50
|
+
// Behaviors
|
|
51
|
+
import { UptimeBehavior } from './behaviors/uptime-behavior.js';
|
|
52
|
+
|
|
53
|
+
// Config
|
|
54
|
+
import { DEFAULT_CONFIG, BEHAVIOR_PRESETS } from './config/defaults.js';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Deep merge two objects
|
|
58
|
+
* @param {Object} target - Target object
|
|
59
|
+
* @param {Object} source - Source object
|
|
60
|
+
* @returns {Object} Merged object
|
|
61
|
+
*/
|
|
62
|
+
function deepMerge(target, source) {
|
|
63
|
+
const output = { ...target };
|
|
64
|
+
if (isObject(target) && isObject(source)) {
|
|
65
|
+
Object.keys(source).forEach(key => {
|
|
66
|
+
if (isObject(source[key])) {
|
|
67
|
+
if (!(key in target)) {
|
|
68
|
+
output[key] = source[key];
|
|
69
|
+
} else {
|
|
70
|
+
output[key] = deepMerge(target[key], source[key]);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
output[key] = source[key];
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return output;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isObject(item) {
|
|
81
|
+
return item && typeof item === 'object' && !Array.isArray(item);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* ReconPlugin
|
|
86
|
+
*
|
|
87
|
+
* Main plugin class that orchestrates reconnaissance operations.
|
|
88
|
+
*/
|
|
89
|
+
export class ReconPlugin extends Plugin {
|
|
90
|
+
static pluginName = 'recon';
|
|
91
|
+
|
|
92
|
+
constructor(config = {}) {
|
|
93
|
+
// Pass config to base class (includes namespace handling)
|
|
94
|
+
super(config);
|
|
95
|
+
|
|
96
|
+
// Apply behavior preset if specified
|
|
97
|
+
let baseConfig = DEFAULT_CONFIG;
|
|
98
|
+
const behaviorMode = config.behavior || 'default';
|
|
99
|
+
|
|
100
|
+
if (config.behavior && BEHAVIOR_PRESETS[config.behavior]) {
|
|
101
|
+
const preset = BEHAVIOR_PRESETS[config.behavior];
|
|
102
|
+
baseConfig = {
|
|
103
|
+
...DEFAULT_CONFIG,
|
|
104
|
+
...preset,
|
|
105
|
+
features: {
|
|
106
|
+
...DEFAULT_CONFIG.features,
|
|
107
|
+
...preset.features
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Emit behavior-applied event
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
this.emit('recon:behavior-applied', {
|
|
114
|
+
mode: config.behavior,
|
|
115
|
+
preset,
|
|
116
|
+
overrides: config.behaviorOverrides || {},
|
|
117
|
+
final: this.config
|
|
118
|
+
});
|
|
119
|
+
}, 0);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Merge with defaults (and preset if applicable)
|
|
123
|
+
this.config = {
|
|
124
|
+
...baseConfig,
|
|
125
|
+
...config,
|
|
126
|
+
behavior: behaviorMode,
|
|
127
|
+
features: deepMerge(
|
|
128
|
+
deepMerge(baseConfig.features, config.features || {}),
|
|
129
|
+
config.behaviorOverrides?.features || {}
|
|
130
|
+
),
|
|
131
|
+
storage: {
|
|
132
|
+
...baseConfig.storage,
|
|
133
|
+
...(config.storage || {})
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Initialize command runner
|
|
138
|
+
this.commandRunner = new CommandRunner();
|
|
139
|
+
|
|
140
|
+
// Initialize process manager (for automatic cleanup)
|
|
141
|
+
this.processManager = processManager;
|
|
142
|
+
|
|
143
|
+
// Initialize managers
|
|
144
|
+
this.storageManager = null; // Initialized in initialize()
|
|
145
|
+
this.targetManager = null;
|
|
146
|
+
this.schedulerManager = null;
|
|
147
|
+
this.dependencyManager = new DependencyManager(this);
|
|
148
|
+
|
|
149
|
+
// Initialize stages
|
|
150
|
+
this.stages = {
|
|
151
|
+
dns: new DnsStage(this),
|
|
152
|
+
certificate: new CertificateStage(this),
|
|
153
|
+
latency: new LatencyStage(this),
|
|
154
|
+
http: new HttpStage(this),
|
|
155
|
+
ports: new PortsStage(this),
|
|
156
|
+
subdomains: new SubdomainsStage(this),
|
|
157
|
+
webDiscovery: new WebDiscoveryStage(this),
|
|
158
|
+
vulnerability: new VulnerabilityStage(this),
|
|
159
|
+
tlsAudit: new TlsAuditStage(this),
|
|
160
|
+
fingerprint: new FingerprintStage(this),
|
|
161
|
+
screenshot: new ScreenshotStage(this),
|
|
162
|
+
osint: new OsintStage(this),
|
|
163
|
+
whois: new WhoisStage(this),
|
|
164
|
+
secrets: new SecretsStage(this),
|
|
165
|
+
asn: new ASNStage(this),
|
|
166
|
+
dnsdumpster: new DNSDumpsterStage(this),
|
|
167
|
+
massdns: new MassDNSStage(this),
|
|
168
|
+
googleDorks: new GoogleDorksStage(this)
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Plugin initialization hook
|
|
174
|
+
*/
|
|
175
|
+
async initialize() {
|
|
176
|
+
// Initialize managers that need database access
|
|
177
|
+
this.storageManager = new StorageManager(this);
|
|
178
|
+
this.targetManager = new TargetManager(this);
|
|
179
|
+
this.schedulerManager = new SchedulerManager(this);
|
|
180
|
+
|
|
181
|
+
// Initialize uptime behavior if enabled
|
|
182
|
+
if (this.config.behaviors?.uptime?.enabled) {
|
|
183
|
+
this.uptimeBehavior = new UptimeBehavior(this, this.config.behaviors.uptime);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Create plugin storage resources
|
|
187
|
+
await this.storageManager.initialize();
|
|
188
|
+
|
|
189
|
+
// Start scheduler if enabled
|
|
190
|
+
if (this.config.scheduler?.enabled) {
|
|
191
|
+
await this.schedulerManager.start();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Check tool dependencies
|
|
195
|
+
await this.dependencyManager.checkAll();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Plugin cleanup hook
|
|
200
|
+
*/
|
|
201
|
+
async cleanup() {
|
|
202
|
+
// Stop scheduler
|
|
203
|
+
if (this.schedulerManager) {
|
|
204
|
+
await this.schedulerManager.stop();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Stop uptime monitoring
|
|
208
|
+
if (this.uptimeBehavior) {
|
|
209
|
+
this.uptimeBehavior.cleanup();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Clear command runner cache
|
|
213
|
+
this.commandRunner.clearCache();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Scan a target (main public API)
|
|
218
|
+
*
|
|
219
|
+
* @param {string|object} target - Target URL/domain or normalized target object
|
|
220
|
+
* @param {object} options - Scan options
|
|
221
|
+
* @returns {Promise<object>} Scan report
|
|
222
|
+
*/
|
|
223
|
+
async scan(target, options = {}) {
|
|
224
|
+
const startTime = Date.now();
|
|
225
|
+
|
|
226
|
+
// Normalize target
|
|
227
|
+
const normalizedTarget = typeof target === 'string'
|
|
228
|
+
? TargetNormalizer.normalize(target)
|
|
229
|
+
: target;
|
|
230
|
+
|
|
231
|
+
// Merge options with config
|
|
232
|
+
const scanConfig = {
|
|
233
|
+
...this.config.features,
|
|
234
|
+
...options
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// Execute scan
|
|
238
|
+
const results = {};
|
|
239
|
+
|
|
240
|
+
// DNS stage
|
|
241
|
+
if (scanConfig.dns !== false) {
|
|
242
|
+
results.dns = await this.stages.dns.execute(normalizedTarget, scanConfig.dns);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Certificate stage
|
|
246
|
+
if (scanConfig.certificate !== false) {
|
|
247
|
+
results.certificate = await this.stages.certificate.execute(normalizedTarget, scanConfig.certificate);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// WHOIS stage
|
|
251
|
+
if (scanConfig.whois !== false) {
|
|
252
|
+
results.whois = await this.stages.whois.execute(normalizedTarget, scanConfig.whois);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Latency stage
|
|
256
|
+
if (scanConfig.latency !== false) {
|
|
257
|
+
results.latency = await this.stages.latency.execute(normalizedTarget, scanConfig.latency);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// HTTP stage
|
|
261
|
+
if (scanConfig.http !== false) {
|
|
262
|
+
results.http = await this.stages.http.execute(normalizedTarget, scanConfig.http);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Ports stage
|
|
266
|
+
if (scanConfig.ports !== false) {
|
|
267
|
+
results.ports = await this.stages.ports.execute(normalizedTarget, scanConfig.ports);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Subdomains stage
|
|
271
|
+
if (scanConfig.subdomains !== false) {
|
|
272
|
+
results.subdomains = await this.stages.subdomains.execute(normalizedTarget, scanConfig.subdomains);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Web discovery stage
|
|
276
|
+
if (scanConfig.webDiscovery !== false) {
|
|
277
|
+
results.webDiscovery = await this.stages.webDiscovery.execute(normalizedTarget, scanConfig.webDiscovery);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Vulnerability stage
|
|
281
|
+
if (scanConfig.vulnerability !== false) {
|
|
282
|
+
results.vulnerability = await this.stages.vulnerability.execute(normalizedTarget, scanConfig.vulnerability);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// TLS audit stage
|
|
286
|
+
if (scanConfig.tlsAudit !== false) {
|
|
287
|
+
results.tlsAudit = await this.stages.tlsAudit.execute(normalizedTarget, scanConfig.tlsAudit);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Fingerprint stage
|
|
291
|
+
if (scanConfig.fingerprint !== false) {
|
|
292
|
+
results.fingerprint = await this.stages.fingerprint.execute(normalizedTarget, scanConfig.fingerprint);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Screenshot stage
|
|
296
|
+
if (scanConfig.screenshot !== false) {
|
|
297
|
+
results.screenshot = await this.stages.screenshot.execute(normalizedTarget, scanConfig.screenshot);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// OSINT stage
|
|
301
|
+
if (scanConfig.osint !== false) {
|
|
302
|
+
results.osint = await this.stages.osint.execute(normalizedTarget, scanConfig.osint);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Secrets detection stage
|
|
306
|
+
if (scanConfig.secrets !== false) {
|
|
307
|
+
results.secrets = await this.stages.secrets.execute(normalizedTarget, scanConfig.secrets);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// ASN stage
|
|
311
|
+
if (scanConfig.asn !== false) {
|
|
312
|
+
results.asn = await this.stages.asn.execute(normalizedTarget, scanConfig.asn);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// DNSDumpster stage
|
|
316
|
+
if (scanConfig.dnsdumpster !== false) {
|
|
317
|
+
results.dnsdumpster = await this.stages.dnsdumpster.execute(normalizedTarget, scanConfig.dnsdumpster);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// MassDNS stage
|
|
321
|
+
if (scanConfig.massdns !== false) {
|
|
322
|
+
results.massdns = await this.stages.massdns.execute(normalizedTarget, scanConfig.massdns);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Google Dorks stage
|
|
326
|
+
if (scanConfig.googleDorks !== false) {
|
|
327
|
+
results.googleDorks = await this.stages.googleDorks.execute(normalizedTarget, scanConfig.googleDorks);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Build consolidated fingerprint
|
|
331
|
+
const fingerprint = FingerprintBuilder.build(results);
|
|
332
|
+
|
|
333
|
+
// Get uptime status if monitoring is enabled
|
|
334
|
+
let uptimeStatus = null;
|
|
335
|
+
if (this.uptimeBehavior) {
|
|
336
|
+
try {
|
|
337
|
+
uptimeStatus = this.uptimeBehavior.getStatus(normalizedTarget.host);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
// Uptime not monitored for this target, skip
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Create report
|
|
344
|
+
const report = {
|
|
345
|
+
id: this._generateReportId(),
|
|
346
|
+
timestamp: new Date().toISOString(),
|
|
347
|
+
target: normalizedTarget,
|
|
348
|
+
duration: Date.now() - startTime,
|
|
349
|
+
status: 'completed',
|
|
350
|
+
results,
|
|
351
|
+
fingerprint,
|
|
352
|
+
uptime: uptimeStatus ? {
|
|
353
|
+
status: uptimeStatus.status,
|
|
354
|
+
uptimePercentage: uptimeStatus.uptimePercentage,
|
|
355
|
+
lastCheck: uptimeStatus.lastCheck,
|
|
356
|
+
isDown: uptimeStatus.isDown,
|
|
357
|
+
consecutiveFails: uptimeStatus.consecutiveFails
|
|
358
|
+
} : null
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// Persist report if storage enabled and manager is initialized
|
|
362
|
+
if (this.config.storage.enabled && this.storageManager) {
|
|
363
|
+
// Layer 1 + 2: Persist to PluginStorage (raw + aggregated)
|
|
364
|
+
await this.storageManager.persistReport(normalizedTarget, report);
|
|
365
|
+
|
|
366
|
+
// Layer 3: Persist to Database Resources (queryable)
|
|
367
|
+
if (this.config.resources.persist) {
|
|
368
|
+
await this.storageManager.persistToResources(report);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Link report to uptime monitoring if enabled
|
|
372
|
+
if (this.uptimeBehavior && uptimeStatus) {
|
|
373
|
+
await this.uptimeBehavior.linkReportToUptime(
|
|
374
|
+
normalizedTarget.host,
|
|
375
|
+
report.id,
|
|
376
|
+
report.timestamp
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return report;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Scan multiple targets in batch
|
|
386
|
+
*/
|
|
387
|
+
async batchScan(targets, options = {}) {
|
|
388
|
+
const results = [];
|
|
389
|
+
|
|
390
|
+
for (const target of targets) {
|
|
391
|
+
try {
|
|
392
|
+
const report = await this.scan(target, options);
|
|
393
|
+
results.push(report);
|
|
394
|
+
} catch (error) {
|
|
395
|
+
results.push({
|
|
396
|
+
target: typeof target === 'string' ? target : target.original,
|
|
397
|
+
status: 'error',
|
|
398
|
+
error: error.message
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return results;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Get scan report by ID
|
|
408
|
+
*/
|
|
409
|
+
async getReport(reportId) {
|
|
410
|
+
return this.storageManager.getReport(reportId);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* List all reports
|
|
415
|
+
*/
|
|
416
|
+
async listReports(options = {}) {
|
|
417
|
+
return this.storageManager.listReports(options);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Get reports for a specific host
|
|
422
|
+
*/
|
|
423
|
+
async getReportsByHost(host, options = {}) {
|
|
424
|
+
if (!this.storageManager) {
|
|
425
|
+
return [];
|
|
426
|
+
}
|
|
427
|
+
return this.storageManager.getReportsByHost(host, options);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Compare two reports and detect changes
|
|
432
|
+
*/
|
|
433
|
+
async compareReports(reportId1, reportId2) {
|
|
434
|
+
const [report1, report2] = await Promise.all([
|
|
435
|
+
this.storageManager.getReport(reportId1),
|
|
436
|
+
this.storageManager.getReport(reportId2)
|
|
437
|
+
]);
|
|
438
|
+
|
|
439
|
+
return DiffDetector.detect(report1, report2);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Generate markdown report
|
|
444
|
+
*/
|
|
445
|
+
generateMarkdownReport(report) {
|
|
446
|
+
return ReportGenerator.generateMarkdown(report);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Generate JSON report
|
|
451
|
+
*/
|
|
452
|
+
generateJSONReport(report) {
|
|
453
|
+
return ReportGenerator.generateJSON(report);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Generate HTML report
|
|
458
|
+
*/
|
|
459
|
+
generateHTMLReport(report) {
|
|
460
|
+
return ReportGenerator.generateHTML(report);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Generate executive summary
|
|
465
|
+
*/
|
|
466
|
+
generateExecutiveSummary(report) {
|
|
467
|
+
return ReportGenerator.generateExecutiveSummary(report);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Generate security audit checklist from scan report
|
|
472
|
+
* @param {Object} report - Scan report
|
|
473
|
+
* @returns {Object} Security audit with findings and recommendations
|
|
474
|
+
*/
|
|
475
|
+
generateSecurityAudit(report) {
|
|
476
|
+
return SecurityAnalyzer.analyze(report);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Generate security audit markdown report
|
|
481
|
+
* @param {Object} report - Scan report
|
|
482
|
+
* @returns {String} Markdown formatted security audit
|
|
483
|
+
*/
|
|
484
|
+
generateSecurityAuditMarkdown(report) {
|
|
485
|
+
const audit = SecurityAnalyzer.analyze(report);
|
|
486
|
+
return SecurityAnalyzer.generateMarkdownReport(audit);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Add dynamic target for scheduled scanning
|
|
491
|
+
*/
|
|
492
|
+
async addTarget(target, schedule = null) {
|
|
493
|
+
return this.targetManager.addTarget(target, schedule);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Remove dynamic target
|
|
498
|
+
*/
|
|
499
|
+
async removeTarget(targetId) {
|
|
500
|
+
return this.targetManager.removeTarget(targetId);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* List all dynamic targets
|
|
505
|
+
*/
|
|
506
|
+
async listTargets() {
|
|
507
|
+
return this.targetManager.listTargets();
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Update target schedule
|
|
512
|
+
*/
|
|
513
|
+
async updateTargetSchedule(targetId, schedule) {
|
|
514
|
+
return this.targetManager.updateSchedule(targetId, schedule);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Get tool availability status
|
|
519
|
+
*/
|
|
520
|
+
async getToolStatus() {
|
|
521
|
+
return this.dependencyManager.getStatus();
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Check if a specific tool is available
|
|
526
|
+
*/
|
|
527
|
+
async isToolAvailable(toolName) {
|
|
528
|
+
return this.commandRunner.isAvailable(toolName);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Run a scheduled sweep of all targets
|
|
533
|
+
*/
|
|
534
|
+
async runScheduledSweep() {
|
|
535
|
+
return this.schedulerManager.runSweep();
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Get diff between latest scans for a host
|
|
540
|
+
*/
|
|
541
|
+
async getLatestDiff(host) {
|
|
542
|
+
const reports = await this.getReportsByHost(host, { limit: 2, sort: 'desc' });
|
|
543
|
+
|
|
544
|
+
if (reports.length < 2) {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return DiffDetector.detect(reports[1], reports[0]);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Get fingerprint for a host
|
|
553
|
+
*/
|
|
554
|
+
async getFingerprint(host) {
|
|
555
|
+
const reports = await this.getReportsByHost(host, { limit: 1 });
|
|
556
|
+
|
|
557
|
+
if (reports.length === 0) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return reports[0].fingerprint;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Generate report ID
|
|
566
|
+
*/
|
|
567
|
+
_generateReportId() {
|
|
568
|
+
return `rpt_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// ============================================================================
|
|
572
|
+
// UPTIME BEHAVIOR METHODS
|
|
573
|
+
// ============================================================================
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Start monitoring uptime for a target
|
|
577
|
+
*/
|
|
578
|
+
async startUptimeMonitoring(target) {
|
|
579
|
+
if (!this.uptimeBehavior) {
|
|
580
|
+
throw new Error('Uptime behavior is not enabled. Set config.behaviors.uptime.enabled = true');
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const normalizedTarget = typeof target === 'string'
|
|
584
|
+
? TargetNormalizer.normalize(target)
|
|
585
|
+
: target;
|
|
586
|
+
|
|
587
|
+
return await this.uptimeBehavior.startMonitoring(normalizedTarget);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Stop monitoring uptime for a target
|
|
592
|
+
*/
|
|
593
|
+
stopUptimeMonitoring(host) {
|
|
594
|
+
if (!this.uptimeBehavior) {
|
|
595
|
+
throw new Error('Uptime behavior is not enabled');
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return this.uptimeBehavior.stopMonitoring(host);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Get uptime status for a target
|
|
603
|
+
*/
|
|
604
|
+
getUptimeStatus(host) {
|
|
605
|
+
if (!this.uptimeBehavior) {
|
|
606
|
+
throw new Error('Uptime behavior is not enabled');
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return this.uptimeBehavior.getStatus(host);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Get uptime statuses for all monitored targets
|
|
614
|
+
*/
|
|
615
|
+
getAllUptimeStatuses() {
|
|
616
|
+
if (!this.uptimeBehavior) {
|
|
617
|
+
throw new Error('Uptime behavior is not enabled');
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
return this.uptimeBehavior.getAllStatuses();
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Load historical uptime status from storage
|
|
625
|
+
*/
|
|
626
|
+
async loadUptimeStatus(host) {
|
|
627
|
+
if (!this.uptimeBehavior) {
|
|
628
|
+
throw new Error('Uptime behavior is not enabled');
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return await this.uptimeBehavior.loadStatus(host);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// ============================================================================
|
|
635
|
+
// BACKWARD COMPATIBILITY METHODS
|
|
636
|
+
// These methods maintain compatibility with the original monolithic API
|
|
637
|
+
// ============================================================================
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Legacy method: runDiagnostics (alias for scan)
|
|
641
|
+
* @deprecated Use scan() instead
|
|
642
|
+
*/
|
|
643
|
+
async runDiagnostics(target, options = {}) {
|
|
644
|
+
return this.scan(target, options);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Legacy method: generateClientReport
|
|
649
|
+
* @deprecated Use generateMarkdownReport() instead
|
|
650
|
+
*/
|
|
651
|
+
async generateClientReport(host, format = 'markdown') {
|
|
652
|
+
const reports = await this.getReportsByHost(host, { limit: 1 });
|
|
653
|
+
|
|
654
|
+
if (reports.length === 0) {
|
|
655
|
+
return format === 'json' ? '{}' : '# No reports found';
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
const report = reports[0];
|
|
659
|
+
|
|
660
|
+
if (format === 'json') {
|
|
661
|
+
return this.generateJSONReport(report);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return this.generateMarkdownReport(report);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Legacy method: _runWebDiscovery (now part of stages)
|
|
669
|
+
* @deprecated Access via stages.webDiscovery.execute() instead
|
|
670
|
+
*/
|
|
671
|
+
async _runWebDiscovery(target, config) {
|
|
672
|
+
return this.stages.webDiscovery.execute(target, config);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* Legacy method: _emitDiffAlerts
|
|
677
|
+
* @deprecated Use compareReports() and handle alerts manually
|
|
678
|
+
*/
|
|
679
|
+
async _emitDiffAlerts(host, report, diffs) {
|
|
680
|
+
for (const diff of diffs) {
|
|
681
|
+
if (diff.severity === 'critical' || diff.severity === 'high') {
|
|
682
|
+
this.emit('recon:alert', {
|
|
683
|
+
host,
|
|
684
|
+
severity: diff.severity,
|
|
685
|
+
change: diff.change,
|
|
686
|
+
timestamp: report.timestamp
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Legacy method: _applyRateLimit
|
|
694
|
+
* @deprecated Rate limiting is now handled automatically
|
|
695
|
+
*/
|
|
696
|
+
async _applyRateLimit(stageName) {
|
|
697
|
+
if (!this.config.rateLimit?.enabled) {
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const delay = this.config.rateLimit.delayBetweenStages || 1000;
|
|
702
|
+
|
|
703
|
+
this.emit('recon:rate-limit-delay', {
|
|
704
|
+
stage: stageName,
|
|
705
|
+
delayMs: delay
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Legacy method: _getResource (proxy to database)
|
|
713
|
+
* @deprecated Access via database.getResource() directly
|
|
714
|
+
*/
|
|
715
|
+
async _getResource(resourceName) {
|
|
716
|
+
if (!this.database) {
|
|
717
|
+
return null;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const fullName = `plg_recon_${resourceName}`;
|
|
721
|
+
|
|
722
|
+
try {
|
|
723
|
+
return await this.database.getResource(fullName);
|
|
724
|
+
} catch (error) {
|
|
725
|
+
return null;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Lifecycle hook: onStop
|
|
731
|
+
* Cleanup all spawned processes when plugin stops
|
|
732
|
+
*/
|
|
733
|
+
async onStop() {
|
|
734
|
+
console.log('[ReconPlugin] Stopping plugin, cleaning up processes...');
|
|
735
|
+
await this.processManager.cleanup({ silent: false });
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Lifecycle hook: onUninstall
|
|
740
|
+
* Cleanup all resources when plugin is uninstalled
|
|
741
|
+
*/
|
|
742
|
+
async onUninstall(options = {}) {
|
|
743
|
+
console.log('[ReconPlugin] Uninstalling plugin, cleaning up processes...');
|
|
744
|
+
await this.processManager.forceCleanup();
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Legacy hook: afterInstall
|
|
749
|
+
* Registers legacy alias database.plugins.network
|
|
750
|
+
*/
|
|
751
|
+
afterInstall() {
|
|
752
|
+
super.afterInstall();
|
|
753
|
+
|
|
754
|
+
// Register legacy alias
|
|
755
|
+
if (this.database) {
|
|
756
|
+
this.database.plugins.network = this;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Legacy hook: afterUninstall
|
|
762
|
+
* Removes legacy alias database.plugins.network
|
|
763
|
+
*/
|
|
764
|
+
afterUninstall() {
|
|
765
|
+
super.afterUninstall();
|
|
766
|
+
|
|
767
|
+
// Cleanup processes
|
|
768
|
+
this.processManager.cleanup({ silent: true }).catch(() => {});
|
|
769
|
+
|
|
770
|
+
// Remove legacy alias
|
|
771
|
+
if (this.database && this.database.plugins.network === this) {
|
|
772
|
+
delete this.database.plugins.network;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Export for backward compatibility
|
|
778
|
+
export default ReconPlugin;
|