s3db.js 13.6.1 → 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.
Files changed (189) hide show
  1. package/README.md +56 -15
  2. package/dist/s3db.cjs +72446 -39022
  3. package/dist/s3db.cjs.map +1 -1
  4. package/dist/s3db.es.js +72172 -38790
  5. package/dist/s3db.es.js.map +1 -1
  6. package/mcp/lib/base-handler.js +157 -0
  7. package/mcp/lib/handlers/connection-handler.js +280 -0
  8. package/mcp/lib/handlers/query-handler.js +533 -0
  9. package/mcp/lib/handlers/resource-handler.js +428 -0
  10. package/mcp/lib/tool-registry.js +336 -0
  11. package/mcp/lib/tools/connection-tools.js +161 -0
  12. package/mcp/lib/tools/query-tools.js +267 -0
  13. package/mcp/lib/tools/resource-tools.js +404 -0
  14. package/package.json +85 -50
  15. package/src/clients/memory-client.class.js +346 -191
  16. package/src/clients/memory-storage.class.js +300 -84
  17. package/src/clients/s3-client.class.js +7 -6
  18. package/src/concerns/geo-encoding.js +19 -2
  19. package/src/concerns/ip.js +59 -9
  20. package/src/concerns/money.js +8 -1
  21. package/src/concerns/password-hashing.js +49 -8
  22. package/src/concerns/plugin-storage.js +186 -18
  23. package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
  24. package/src/database.class.js +139 -29
  25. package/src/errors.js +332 -42
  26. package/src/plugins/api/auth/oidc-auth.js +66 -17
  27. package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
  28. package/src/plugins/api/auth/strategies/factory.class.js +63 -0
  29. package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
  30. package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
  31. package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
  32. package/src/plugins/api/concerns/failban-manager.js +106 -57
  33. package/src/plugins/api/concerns/route-context.js +601 -0
  34. package/src/plugins/api/index.js +168 -40
  35. package/src/plugins/api/routes/auth-routes.js +198 -30
  36. package/src/plugins/api/routes/resource-routes.js +19 -4
  37. package/src/plugins/api/server/health-manager.class.js +163 -0
  38. package/src/plugins/api/server/middleware-chain.class.js +310 -0
  39. package/src/plugins/api/server/router.class.js +472 -0
  40. package/src/plugins/api/server.js +280 -1303
  41. package/src/plugins/api/utils/custom-routes.js +17 -5
  42. package/src/plugins/api/utils/guards.js +76 -17
  43. package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
  44. package/src/plugins/api/utils/openapi-generator.js +7 -6
  45. package/src/plugins/audit.plugin.js +30 -8
  46. package/src/plugins/backup.plugin.js +110 -14
  47. package/src/plugins/cache/cache.class.js +22 -5
  48. package/src/plugins/cache/filesystem-cache.class.js +116 -19
  49. package/src/plugins/cache/memory-cache.class.js +211 -57
  50. package/src/plugins/cache/multi-tier-cache.class.js +371 -0
  51. package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
  52. package/src/plugins/cache/redis-cache.class.js +552 -0
  53. package/src/plugins/cache/s3-cache.class.js +17 -8
  54. package/src/plugins/cache.plugin.js +176 -61
  55. package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
  56. package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
  57. package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
  58. package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
  59. package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
  60. package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
  61. package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
  62. package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
  63. package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
  64. package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
  65. package/src/plugins/cloud-inventory/index.js +29 -8
  66. package/src/plugins/cloud-inventory/registry.js +64 -42
  67. package/src/plugins/cloud-inventory.plugin.js +240 -138
  68. package/src/plugins/concerns/plugin-dependencies.js +54 -0
  69. package/src/plugins/concerns/resource-names.js +100 -0
  70. package/src/plugins/consumers/index.js +10 -2
  71. package/src/plugins/consumers/sqs-consumer.js +12 -2
  72. package/src/plugins/cookie-farm-suite.plugin.js +278 -0
  73. package/src/plugins/cookie-farm.errors.js +73 -0
  74. package/src/plugins/cookie-farm.plugin.js +869 -0
  75. package/src/plugins/costs.plugin.js +7 -1
  76. package/src/plugins/eventual-consistency/analytics.js +94 -19
  77. package/src/plugins/eventual-consistency/config.js +15 -7
  78. package/src/plugins/eventual-consistency/consolidation.js +29 -11
  79. package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
  80. package/src/plugins/eventual-consistency/helpers.js +39 -14
  81. package/src/plugins/eventual-consistency/install.js +21 -2
  82. package/src/plugins/eventual-consistency/utils.js +32 -10
  83. package/src/plugins/fulltext.plugin.js +38 -11
  84. package/src/plugins/geo.plugin.js +61 -9
  85. package/src/plugins/identity/concerns/config.js +61 -0
  86. package/src/plugins/identity/concerns/mfa-manager.js +15 -2
  87. package/src/plugins/identity/concerns/rate-limit.js +124 -0
  88. package/src/plugins/identity/concerns/resource-schemas.js +9 -1
  89. package/src/plugins/identity/concerns/token-generator.js +29 -4
  90. package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
  91. package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
  92. package/src/plugins/identity/drivers/index.js +18 -0
  93. package/src/plugins/identity/drivers/password-driver.js +122 -0
  94. package/src/plugins/identity/email-service.js +17 -2
  95. package/src/plugins/identity/index.js +413 -69
  96. package/src/plugins/identity/oauth2-server.js +413 -30
  97. package/src/plugins/identity/oidc-discovery.js +16 -8
  98. package/src/plugins/identity/rsa-keys.js +115 -35
  99. package/src/plugins/identity/server.js +166 -45
  100. package/src/plugins/identity/session-manager.js +53 -7
  101. package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
  102. package/src/plugins/identity/ui/routes.js +363 -255
  103. package/src/plugins/importer/index.js +153 -20
  104. package/src/plugins/index.js +9 -2
  105. package/src/plugins/kubernetes-inventory/index.js +6 -0
  106. package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
  107. package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
  108. package/src/plugins/kubernetes-inventory.plugin.js +980 -0
  109. package/src/plugins/metrics.plugin.js +64 -16
  110. package/src/plugins/ml/base-model.class.js +25 -15
  111. package/src/plugins/ml/regression-model.class.js +1 -1
  112. package/src/plugins/ml.errors.js +57 -25
  113. package/src/plugins/ml.plugin.js +28 -4
  114. package/src/plugins/namespace.js +210 -0
  115. package/src/plugins/plugin.class.js +180 -8
  116. package/src/plugins/puppeteer/console-monitor.js +729 -0
  117. package/src/plugins/puppeteer/cookie-manager.js +492 -0
  118. package/src/plugins/puppeteer/network-monitor.js +816 -0
  119. package/src/plugins/puppeteer/performance-manager.js +746 -0
  120. package/src/plugins/puppeteer/proxy-manager.js +478 -0
  121. package/src/plugins/puppeteer/stealth-manager.js +556 -0
  122. package/src/plugins/puppeteer.errors.js +81 -0
  123. package/src/plugins/puppeteer.plugin.js +1327 -0
  124. package/src/plugins/queue-consumer.plugin.js +69 -14
  125. package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
  126. package/src/plugins/recon/concerns/command-runner.js +148 -0
  127. package/src/plugins/recon/concerns/diff-detector.js +372 -0
  128. package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
  129. package/src/plugins/recon/concerns/process-manager.js +338 -0
  130. package/src/plugins/recon/concerns/report-generator.js +478 -0
  131. package/src/plugins/recon/concerns/security-analyzer.js +571 -0
  132. package/src/plugins/recon/concerns/target-normalizer.js +68 -0
  133. package/src/plugins/recon/config/defaults.js +321 -0
  134. package/src/plugins/recon/config/resources.js +370 -0
  135. package/src/plugins/recon/index.js +778 -0
  136. package/src/plugins/recon/managers/dependency-manager.js +174 -0
  137. package/src/plugins/recon/managers/scheduler-manager.js +179 -0
  138. package/src/plugins/recon/managers/storage-manager.js +745 -0
  139. package/src/plugins/recon/managers/target-manager.js +274 -0
  140. package/src/plugins/recon/stages/asn-stage.js +314 -0
  141. package/src/plugins/recon/stages/certificate-stage.js +84 -0
  142. package/src/plugins/recon/stages/dns-stage.js +107 -0
  143. package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
  144. package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
  145. package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
  146. package/src/plugins/recon/stages/http-stage.js +89 -0
  147. package/src/plugins/recon/stages/latency-stage.js +148 -0
  148. package/src/plugins/recon/stages/massdns-stage.js +302 -0
  149. package/src/plugins/recon/stages/osint-stage.js +1373 -0
  150. package/src/plugins/recon/stages/ports-stage.js +169 -0
  151. package/src/plugins/recon/stages/screenshot-stage.js +94 -0
  152. package/src/plugins/recon/stages/secrets-stage.js +514 -0
  153. package/src/plugins/recon/stages/subdomains-stage.js +295 -0
  154. package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
  155. package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
  156. package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
  157. package/src/plugins/recon/stages/whois-stage.js +349 -0
  158. package/src/plugins/recon.plugin.js +75 -0
  159. package/src/plugins/recon.plugin.js.backup +2635 -0
  160. package/src/plugins/relation.errors.js +87 -14
  161. package/src/plugins/replicator.plugin.js +514 -137
  162. package/src/plugins/replicators/base-replicator.class.js +89 -1
  163. package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
  164. package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
  165. package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
  166. package/src/plugins/replicators/mysql-replicator.class.js +52 -17
  167. package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
  168. package/src/plugins/replicators/postgres-replicator.class.js +62 -27
  169. package/src/plugins/replicators/s3db-replicator.class.js +25 -18
  170. package/src/plugins/replicators/schema-sync.helper.js +3 -3
  171. package/src/plugins/replicators/sqs-replicator.class.js +8 -2
  172. package/src/plugins/replicators/turso-replicator.class.js +23 -3
  173. package/src/plugins/replicators/webhook-replicator.class.js +42 -4
  174. package/src/plugins/s3-queue.plugin.js +464 -65
  175. package/src/plugins/scheduler.plugin.js +20 -6
  176. package/src/plugins/state-machine.plugin.js +40 -9
  177. package/src/plugins/tfstate/base-driver.js +28 -4
  178. package/src/plugins/tfstate/errors.js +65 -10
  179. package/src/plugins/tfstate/filesystem-driver.js +52 -8
  180. package/src/plugins/tfstate/index.js +163 -90
  181. package/src/plugins/tfstate/s3-driver.js +64 -6
  182. package/src/plugins/ttl.plugin.js +72 -17
  183. package/src/plugins/vector/distances.js +18 -12
  184. package/src/plugins/vector/kmeans.js +26 -4
  185. package/src/resource.class.js +115 -19
  186. package/src/testing/factory.class.js +20 -3
  187. package/src/testing/seeder.class.js +7 -1
  188. package/src/clients/memory-client.md +0 -917
  189. package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
@@ -27,6 +27,8 @@
27
27
  * The plugin normalizes the payload, computes configuration digests and
28
28
  * manages versioning/diffing.
29
29
  */
30
+ import { PluginError } from '../../../errors.js';
31
+
30
32
  export class BaseCloudDriver {
31
33
  /**
32
34
  * @param {Object} options
@@ -48,7 +50,13 @@ export class BaseCloudDriver {
48
50
  } = options;
49
51
 
50
52
  if (!driver) {
51
- throw new Error('Cloud driver requires a "driver" identifier');
53
+ throw new PluginError('Cloud driver requires a "driver" identifier', {
54
+ pluginName: 'CloudInventoryPlugin',
55
+ operation: 'cloudDriver:constructor',
56
+ statusCode: 500,
57
+ retriable: false,
58
+ suggestion: 'Specify the driver key (e.g. "aws", "gcp") when instantiating a cloud inventory driver.'
59
+ });
52
60
  }
53
61
 
54
62
  this.id = id || driver;
@@ -77,7 +85,13 @@ export class BaseCloudDriver {
77
85
  */
78
86
  // eslint-disable-next-line no-unused-vars
79
87
  async listResources(options = {}) {
80
- throw new Error(`Driver "${this.driver}" does not implement listResources()`);
88
+ throw new PluginError(`Driver "${this.driver}" does not implement listResources()`, {
89
+ pluginName: 'CloudInventoryPlugin',
90
+ operation: 'cloudDriver:listResources',
91
+ statusCode: 500,
92
+ retriable: false,
93
+ suggestion: 'Implement listResources(options) in the concrete cloud driver to fetch inventory data.'
94
+ });
81
95
  }
82
96
 
83
97
  /**
@@ -1,4 +1,5 @@
1
1
  import { BaseCloudDriver } from './base-driver.js';
2
+ import { PluginError } from '../../../errors.js';
2
3
 
3
4
  /**
4
5
  * Production-ready Cloudflare inventory driver using official cloudflare SDK.
@@ -47,7 +48,13 @@ export class CloudflareInventoryDriver extends BaseCloudDriver {
47
48
  this._accountId = credentials.accountId || this.config?.accountId || process.env.CLOUDFLARE_ACCOUNT_ID;
48
49
 
49
50
  if (!this._apiToken) {
50
- throw new Error('Cloudflare API token is required. Provide via credentials.apiToken or CLOUDFLARE_API_TOKEN env var.');
51
+ throw new PluginError('Cloudflare API token is required. Provide via credentials.apiToken or CLOUDFLARE_API_TOKEN env var.', {
52
+ pluginName: 'CloudInventoryPlugin',
53
+ operation: 'cloudflare:initClient',
54
+ statusCode: 400,
55
+ retriable: false,
56
+ suggestion: 'Populate credentials.apiToken or set the CLOUDFLARE_API_TOKEN environment variable before initializing the Cloudflare driver.'
57
+ });
51
58
  }
52
59
 
53
60
  // Lazy import
@@ -1,4 +1,5 @@
1
1
  import { BaseCloudDriver } from './base-driver.js';
2
+ import { PluginError } from '../../../errors.js';
2
3
 
3
4
  /**
4
5
  * Production-ready DigitalOcean inventory driver using digitalocean-js library.
@@ -59,7 +60,13 @@ export class DigitalOceanInventoryDriver extends BaseCloudDriver {
59
60
  this._apiToken = credentials.token || credentials.apiToken || process.env.DIGITALOCEAN_TOKEN;
60
61
 
61
62
  if (!this._apiToken) {
62
- throw new Error('DigitalOcean API token is required. Provide via credentials.token or DIGITALOCEAN_TOKEN env var.');
63
+ throw new PluginError('DigitalOcean API token is required. Provide via credentials.token or DIGITALOCEAN_TOKEN env var.', {
64
+ pluginName: 'CloudInventoryPlugin',
65
+ operation: 'digitalocean:initClient',
66
+ statusCode: 400,
67
+ retriable: false,
68
+ suggestion: 'Set credentials.token or the DIGITALOCEAN_TOKEN environment variable before initializing the driver.'
69
+ });
63
70
  }
64
71
 
65
72
  // Lazy import to keep core package lightweight
@@ -1,4 +1,5 @@
1
1
  import { BaseCloudDriver } from './base-driver.js';
2
+ import { PluginError } from '../../../errors.js';
2
3
 
3
4
  /**
4
5
  * Production-ready Hetzner Cloud inventory driver using hcloud-js library.
@@ -47,7 +48,13 @@ export class HetznerInventoryDriver extends BaseCloudDriver {
47
48
  this._apiToken = credentials.token || credentials.apiToken || process.env.HETZNER_TOKEN;
48
49
 
49
50
  if (!this._apiToken) {
50
- throw new Error('Hetzner API token is required. Provide via credentials.token or HETZNER_TOKEN env var.');
51
+ throw new PluginError('Hetzner API token is required. Provide via credentials.token or HETZNER_TOKEN env var.', {
52
+ pluginName: 'CloudInventoryPlugin',
53
+ operation: 'hetzner:initClient',
54
+ statusCode: 400,
55
+ retriable: false,
56
+ suggestion: 'Set credentials.token or HETZNER_TOKEN prior to initializing the Hetzner driver.'
57
+ });
51
58
  }
52
59
 
53
60
  // Lazy import to keep core package lightweight
@@ -1,4 +1,5 @@
1
1
  import { BaseCloudDriver } from './base-driver.js';
2
+ import { PluginError } from '../../../errors.js';
2
3
 
3
4
  /**
4
5
  * Production-ready Linode (Akamai Cloud) inventory driver using official @linode/api-v4 SDK.
@@ -52,7 +53,13 @@ export class LinodeInventoryDriver extends BaseCloudDriver {
52
53
  this._apiToken = credentials.token || credentials.apiToken || process.env.LINODE_TOKEN;
53
54
 
54
55
  if (!this._apiToken) {
55
- throw new Error('Linode API token is required. Provide via credentials.token or LINODE_TOKEN env var.');
56
+ throw new PluginError('Linode API token is required. Provide via credentials.token or LINODE_TOKEN env var.', {
57
+ pluginName: 'CloudInventoryPlugin',
58
+ operation: 'linode:initClient',
59
+ statusCode: 400,
60
+ retriable: false,
61
+ suggestion: 'Set credentials.token or LINODE_TOKEN before running the Linode inventory driver.'
62
+ });
56
63
  }
57
64
 
58
65
  // Import and set token
@@ -1,4 +1,5 @@
1
1
  import { BaseCloudDriver } from './base-driver.js';
2
+ import { PluginError } from '../../../errors.js';
2
3
 
3
4
  /**
4
5
  * Production-ready MongoDB Atlas inventory driver using mongodb-atlas-api-client.
@@ -54,7 +55,13 @@ export class MongoDBAtlasInventoryDriver extends BaseCloudDriver {
54
55
  this._organizationId = credentials.organizationId || this._organizationId;
55
56
 
56
57
  if (!this._publicKey || !this._privateKey) {
57
- throw new Error('MongoDB Atlas API keys are required. Provide via credentials.publicKey/privateKey or env vars.');
58
+ throw new PluginError('MongoDB Atlas API keys are required. Provide via credentials.publicKey/privateKey or env vars.', {
59
+ pluginName: 'CloudInventoryPlugin',
60
+ operation: 'mongodbAtlas:initClient',
61
+ statusCode: 400,
62
+ retriable: false,
63
+ suggestion: 'Set credentials.publicKey/privateKey or env variables MONGODB_ATLAS_PUBLIC_KEY / MONGODB_ATLAS_PRIVATE_KEY.'
64
+ });
58
65
  }
59
66
 
60
67
  this.logger('info', 'MongoDB Atlas credentials initialized', {
@@ -1,4 +1,5 @@
1
1
  import { BaseCloudDriver } from './base-driver.js';
2
+ import { PluginError } from '../../../errors.js';
2
3
 
3
4
  /**
4
5
  * Production-ready Vultr inventory driver using official @vultr/vultr-node SDK.
@@ -50,7 +51,13 @@ export class VultrInventoryDriver extends BaseCloudDriver {
50
51
  this._apiKey = credentials.apiKey || credentials.token || process.env.VULTR_API_KEY;
51
52
 
52
53
  if (!this._apiKey) {
53
- throw new Error('Vultr API key is required. Provide via credentials.apiKey or VULTR_API_KEY env var.');
54
+ throw new PluginError('Vultr API key is required. Provide via credentials.apiKey or VULTR_API_KEY env var.', {
55
+ pluginName: 'CloudInventoryPlugin',
56
+ operation: 'vultr:initClient',
57
+ statusCode: 400,
58
+ retriable: false,
59
+ suggestion: 'Set credentials.apiKey or the VULTR_API_KEY environment variable before initializing the driver.'
60
+ });
54
61
  }
55
62
 
56
63
  // Lazy import to keep core package lightweight
@@ -9,12 +9,33 @@ export {
9
9
  export {
10
10
  AwsInventoryDriver
11
11
  } from './drivers/aws-driver.js';
12
-
13
12
  export {
14
- AwsMockDriver,
15
- GcpMockDriver,
16
- DigitalOceanMockDriver,
17
- OracleMockDriver,
18
- AzureMockDriver,
19
- VultrMockDriver
20
- } from './drivers/mock-drivers.js';
13
+ GcpInventoryDriver
14
+ } from './drivers/gcp-driver.js';
15
+ export {
16
+ AzureInventoryDriver
17
+ } from './drivers/azure-driver.js';
18
+ export {
19
+ DigitalOceanInventoryDriver
20
+ } from './drivers/digitalocean-driver.js';
21
+ export {
22
+ OracleInventoryDriver
23
+ } from './drivers/oracle-driver.js';
24
+ export {
25
+ VultrInventoryDriver
26
+ } from './drivers/vultr-driver.js';
27
+ export {
28
+ LinodeInventoryDriver
29
+ } from './drivers/linode-driver.js';
30
+ export {
31
+ HetznerInventoryDriver
32
+ } from './drivers/hetzner-driver.js';
33
+ export {
34
+ AlibabaInventoryDriver
35
+ } from './drivers/alibaba-driver.js';
36
+ export {
37
+ CloudflareInventoryDriver
38
+ } from './drivers/cloudflare-driver.js';
39
+ export {
40
+ MongoDBAtlasInventoryDriver
41
+ } from './drivers/mongodb-atlas-driver.js';
@@ -10,20 +10,7 @@ import { HetznerInventoryDriver } from './drivers/hetzner-driver.js';
10
10
  import { AlibabaInventoryDriver } from './drivers/alibaba-driver.js';
11
11
  import { CloudflareInventoryDriver } from './drivers/cloudflare-driver.js';
12
12
  import { MongoDBAtlasInventoryDriver } from './drivers/mongodb-atlas-driver.js';
13
- import {
14
- AwsMockDriver,
15
- GcpMockDriver,
16
- DigitalOceanMockDriver,
17
- OracleMockDriver,
18
- AzureMockDriver,
19
- VultrMockDriver,
20
- LinodeMockDriver,
21
- HetznerMockDriver,
22
- AlibabaMockDriver,
23
- CloudflareMockDriver,
24
- MongoDBAtlasMockDriver
25
- } from './drivers/mock-drivers.js';
26
-
13
+ import { PluginError } from '../../errors.js';
27
14
  const CLOUD_DRIVERS = new Map();
28
15
 
29
16
  /**
@@ -33,11 +20,23 @@ const CLOUD_DRIVERS = new Map();
33
20
  */
34
21
  export function registerCloudDriver(name, factory) {
35
22
  if (!name || typeof name !== 'string') {
36
- throw new Error('registerCloudDriver: name must be a non-empty string');
23
+ throw new PluginError('registerCloudDriver: name must be a non-empty string', {
24
+ pluginName: 'CloudInventoryPlugin',
25
+ operation: 'registry:register',
26
+ statusCode: 400,
27
+ retriable: false,
28
+ suggestion: 'Call registerCloudDriver with a string identifier, e.g. registerCloudDriver("aws", factory).'
29
+ });
37
30
  }
38
31
 
39
32
  if (typeof factory !== 'function') {
40
- throw new Error(`registerCloudDriver("${name}") expects a factory function`);
33
+ throw new PluginError(`registerCloudDriver("${name}") expects a factory function`, {
34
+ pluginName: 'CloudInventoryPlugin',
35
+ operation: 'registry:register',
36
+ statusCode: 400,
37
+ retriable: false,
38
+ suggestion: 'Pass a factory function that returns an instance of BaseCloudDriver.'
39
+ });
41
40
  }
42
41
 
43
42
  CLOUD_DRIVERS.set(name, factory);
@@ -51,12 +50,29 @@ export function registerCloudDriver(name, factory) {
51
50
  */
52
51
  export function createCloudDriver(name, options) {
53
52
  if (!CLOUD_DRIVERS.has(name)) {
54
- throw new Error(`Cloud driver "${name}" is not registered. Registered drivers: ${[...CLOUD_DRIVERS.keys()].join(', ') || 'none'}`);
53
+ throw new PluginError(`Cloud driver "${name}" is not registered.`, {
54
+ pluginName: 'CloudInventoryPlugin',
55
+ operation: 'registry:create',
56
+ statusCode: 400,
57
+ retriable: false,
58
+ suggestion: `Register the driver via registerCloudDriver before creating it. Registered drivers: ${[...CLOUD_DRIVERS.keys()].join(', ') || 'none'}`
59
+ });
60
+ }
61
+
62
+ const resolvedOptions = { ...(options || {}) };
63
+ if (!resolvedOptions.driver) {
64
+ resolvedOptions.driver = name;
55
65
  }
56
66
 
57
- const driver = CLOUD_DRIVERS.get(name)(options);
67
+ const driver = CLOUD_DRIVERS.get(name)(resolvedOptions);
58
68
  if (!(driver instanceof BaseCloudDriver)) {
59
- throw new Error(`Driver "${name}" factory must return an instance of BaseCloudDriver`);
69
+ throw new PluginError(`Driver "${name}" factory must return an instance of BaseCloudDriver`, {
70
+ pluginName: 'CloudInventoryPlugin',
71
+ operation: 'registry:create',
72
+ statusCode: 500,
73
+ retriable: false,
74
+ suggestion: 'Ensure the factory returns a class extending BaseCloudDriver.'
75
+ });
60
76
  }
61
77
  return driver;
62
78
  }
@@ -76,24 +92,48 @@ export function listCloudDrivers() {
76
92
  */
77
93
  export function validateCloudDefinition(cloud) {
78
94
  if (!cloud || typeof cloud !== 'object') {
79
- throw new Error('Each cloud configuration must be an object');
95
+ throw new PluginError('Each cloud configuration must be an object', {
96
+ pluginName: 'CloudInventoryPlugin',
97
+ operation: 'registry:validateDefinition',
98
+ statusCode: 400,
99
+ retriable: false,
100
+ suggestion: 'Provide cloud definitions as objects (e.g. { driver: "aws", credentials: {...} }).'
101
+ });
80
102
  }
81
103
 
82
104
  const { driver, credentials } = cloud;
83
105
  if (!driver || typeof driver !== 'string') {
84
- throw new Error('Cloud configuration requires a "driver" string');
106
+ throw new PluginError('Cloud configuration requires a "driver" string', {
107
+ pluginName: 'CloudInventoryPlugin',
108
+ operation: 'registry:validateDefinition',
109
+ statusCode: 400,
110
+ retriable: false,
111
+ suggestion: 'Set the driver field to a registered driver name.'
112
+ });
85
113
  }
86
114
 
87
115
  if (!CLOUD_DRIVERS.has(driver)) {
88
- throw new Error(`Cloud driver "${driver}" is not registered`);
116
+ throw new PluginError(`Cloud driver "${driver}" is not registered`, {
117
+ pluginName: 'CloudInventoryPlugin',
118
+ operation: 'registry:validateDefinition',
119
+ statusCode: 400,
120
+ retriable: false,
121
+ suggestion: 'Register the driver via registerCloudDriver before referencing it in configuration.'
122
+ });
89
123
  }
90
124
 
91
125
  if (!credentials || typeof credentials !== 'object') {
92
- throw new Error(`Cloud "${driver}" requires a credentials object`);
126
+ throw new PluginError(`Cloud "${driver}" requires a credentials object`, {
127
+ pluginName: 'CloudInventoryPlugin',
128
+ operation: 'registry:validateDefinition',
129
+ statusCode: 400,
130
+ retriable: false,
131
+ suggestion: 'Provide credentials for each cloud entry (e.g. credentials: { token: "..." }).'
132
+ });
93
133
  }
94
134
  }
95
135
 
96
- // Register a no-op driver as a placeholder / mock implementation.
136
+ // Register a no-op driver as a placeholder implementation.
97
137
  registerCloudDriver('noop', (options = {}) => {
98
138
  class NoopDriver extends BaseCloudDriver {
99
139
  async listResources() {
@@ -107,13 +147,6 @@ registerCloudDriver('noop', (options = {}) => {
107
147
  });
108
148
  });
109
149
 
110
- function registerMockDriver(names, DriverClass) {
111
- const list = Array.isArray(names) ? names : [names];
112
- for (const name of list) {
113
- registerCloudDriver(name, (options = {}) => new DriverClass(options));
114
- }
115
- }
116
-
117
150
  registerCloudDriver('aws', (options = {}) => new AwsInventoryDriver(options));
118
151
  registerCloudDriver('gcp', (options = {}) => new GcpInventoryDriver(options));
119
152
  registerCloudDriver('vultr', (options = {}) => new VultrInventoryDriver(options));
@@ -131,16 +164,5 @@ registerCloudDriver('cloudflare', (options = {}) => new CloudflareInventoryDrive
131
164
  registerCloudDriver('cf', (options = {}) => new CloudflareInventoryDriver(options));
132
165
  registerCloudDriver('mongodb-atlas', (options = {}) => new MongoDBAtlasInventoryDriver(options));
133
166
  registerCloudDriver('atlas', (options = {}) => new MongoDBAtlasInventoryDriver(options));
134
- registerMockDriver('aws-mock', AwsMockDriver);
135
- registerMockDriver('gcp-mock', GcpMockDriver);
136
- registerMockDriver('vultr-mock', VultrMockDriver);
137
- registerMockDriver(['digitalocean-mock', 'do-mock'], DigitalOceanMockDriver);
138
- registerMockDriver(['oracle-mock', 'oci-mock'], OracleMockDriver);
139
- registerMockDriver(['azure-mock', 'az-mock'], AzureMockDriver);
140
- registerMockDriver('linode-mock', LinodeMockDriver);
141
- registerMockDriver('hetzner-mock', HetznerMockDriver);
142
- registerMockDriver(['alibaba-mock', 'aliyun-mock'], AlibabaMockDriver);
143
- registerMockDriver(['cloudflare-mock', 'cf-mock'], CloudflareMockDriver);
144
- registerMockDriver(['mongodb-atlas-mock', 'atlas-mock'], MongoDBAtlasMockDriver);
145
167
 
146
168
  export { BaseCloudDriver } from './drivers/base-driver.js';