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.
Files changed (193) hide show
  1. package/README.md +139 -43
  2. package/dist/s3db.cjs +72425 -38970
  3. package/dist/s3db.cjs.map +1 -1
  4. package/dist/s3db.es.js +72177 -38764
  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 +94 -49
  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/opengraph-helper.js +116 -0
  34. package/src/plugins/api/concerns/route-context.js +601 -0
  35. package/src/plugins/api/concerns/state-machine.js +288 -0
  36. package/src/plugins/api/index.js +180 -41
  37. package/src/plugins/api/routes/auth-routes.js +198 -30
  38. package/src/plugins/api/routes/resource-routes.js +19 -4
  39. package/src/plugins/api/server/health-manager.class.js +163 -0
  40. package/src/plugins/api/server/middleware-chain.class.js +310 -0
  41. package/src/plugins/api/server/router.class.js +472 -0
  42. package/src/plugins/api/server.js +280 -1303
  43. package/src/plugins/api/utils/custom-routes.js +17 -5
  44. package/src/plugins/api/utils/guards.js +76 -17
  45. package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
  46. package/src/plugins/api/utils/openapi-generator.js +7 -6
  47. package/src/plugins/api/utils/template-engine.js +77 -3
  48. package/src/plugins/audit.plugin.js +30 -8
  49. package/src/plugins/backup.plugin.js +110 -14
  50. package/src/plugins/cache/cache.class.js +22 -5
  51. package/src/plugins/cache/filesystem-cache.class.js +116 -19
  52. package/src/plugins/cache/memory-cache.class.js +211 -57
  53. package/src/plugins/cache/multi-tier-cache.class.js +371 -0
  54. package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
  55. package/src/plugins/cache/redis-cache.class.js +552 -0
  56. package/src/plugins/cache/s3-cache.class.js +17 -8
  57. package/src/plugins/cache.plugin.js +176 -61
  58. package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
  59. package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
  60. package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
  61. package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
  62. package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
  63. package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
  64. package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
  65. package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
  66. package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
  67. package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
  68. package/src/plugins/cloud-inventory/index.js +29 -8
  69. package/src/plugins/cloud-inventory/registry.js +64 -42
  70. package/src/plugins/cloud-inventory.plugin.js +240 -138
  71. package/src/plugins/concerns/plugin-dependencies.js +54 -0
  72. package/src/plugins/concerns/resource-names.js +100 -0
  73. package/src/plugins/consumers/index.js +10 -2
  74. package/src/plugins/consumers/sqs-consumer.js +12 -2
  75. package/src/plugins/cookie-farm-suite.plugin.js +278 -0
  76. package/src/plugins/cookie-farm.errors.js +73 -0
  77. package/src/plugins/cookie-farm.plugin.js +869 -0
  78. package/src/plugins/costs.plugin.js +7 -1
  79. package/src/plugins/eventual-consistency/analytics.js +94 -19
  80. package/src/plugins/eventual-consistency/config.js +15 -7
  81. package/src/plugins/eventual-consistency/consolidation.js +29 -11
  82. package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
  83. package/src/plugins/eventual-consistency/helpers.js +39 -14
  84. package/src/plugins/eventual-consistency/install.js +21 -2
  85. package/src/plugins/eventual-consistency/utils.js +32 -10
  86. package/src/plugins/fulltext.plugin.js +38 -11
  87. package/src/plugins/geo.plugin.js +61 -9
  88. package/src/plugins/identity/concerns/config.js +61 -0
  89. package/src/plugins/identity/concerns/mfa-manager.js +15 -2
  90. package/src/plugins/identity/concerns/rate-limit.js +124 -0
  91. package/src/plugins/identity/concerns/resource-schemas.js +9 -1
  92. package/src/plugins/identity/concerns/token-generator.js +29 -4
  93. package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
  94. package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
  95. package/src/plugins/identity/drivers/index.js +18 -0
  96. package/src/plugins/identity/drivers/password-driver.js +122 -0
  97. package/src/plugins/identity/email-service.js +17 -2
  98. package/src/plugins/identity/index.js +413 -69
  99. package/src/plugins/identity/oauth2-server.js +413 -30
  100. package/src/plugins/identity/oidc-discovery.js +16 -8
  101. package/src/plugins/identity/rsa-keys.js +115 -35
  102. package/src/plugins/identity/server.js +166 -45
  103. package/src/plugins/identity/session-manager.js +53 -7
  104. package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
  105. package/src/plugins/identity/ui/routes.js +363 -255
  106. package/src/plugins/importer/index.js +153 -20
  107. package/src/plugins/index.js +9 -2
  108. package/src/plugins/kubernetes-inventory/index.js +6 -0
  109. package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
  110. package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
  111. package/src/plugins/kubernetes-inventory.plugin.js +980 -0
  112. package/src/plugins/metrics.plugin.js +64 -16
  113. package/src/plugins/ml/base-model.class.js +25 -15
  114. package/src/plugins/ml/regression-model.class.js +1 -1
  115. package/src/plugins/ml.errors.js +57 -25
  116. package/src/plugins/ml.plugin.js +28 -4
  117. package/src/plugins/namespace.js +210 -0
  118. package/src/plugins/plugin.class.js +180 -8
  119. package/src/plugins/puppeteer/console-monitor.js +729 -0
  120. package/src/plugins/puppeteer/cookie-manager.js +492 -0
  121. package/src/plugins/puppeteer/network-monitor.js +816 -0
  122. package/src/plugins/puppeteer/performance-manager.js +746 -0
  123. package/src/plugins/puppeteer/proxy-manager.js +478 -0
  124. package/src/plugins/puppeteer/stealth-manager.js +556 -0
  125. package/src/plugins/puppeteer.errors.js +81 -0
  126. package/src/plugins/puppeteer.plugin.js +1327 -0
  127. package/src/plugins/queue-consumer.plugin.js +69 -14
  128. package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
  129. package/src/plugins/recon/concerns/command-runner.js +148 -0
  130. package/src/plugins/recon/concerns/diff-detector.js +372 -0
  131. package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
  132. package/src/plugins/recon/concerns/process-manager.js +338 -0
  133. package/src/plugins/recon/concerns/report-generator.js +478 -0
  134. package/src/plugins/recon/concerns/security-analyzer.js +571 -0
  135. package/src/plugins/recon/concerns/target-normalizer.js +68 -0
  136. package/src/plugins/recon/config/defaults.js +321 -0
  137. package/src/plugins/recon/config/resources.js +370 -0
  138. package/src/plugins/recon/index.js +778 -0
  139. package/src/plugins/recon/managers/dependency-manager.js +174 -0
  140. package/src/plugins/recon/managers/scheduler-manager.js +179 -0
  141. package/src/plugins/recon/managers/storage-manager.js +745 -0
  142. package/src/plugins/recon/managers/target-manager.js +274 -0
  143. package/src/plugins/recon/stages/asn-stage.js +314 -0
  144. package/src/plugins/recon/stages/certificate-stage.js +84 -0
  145. package/src/plugins/recon/stages/dns-stage.js +107 -0
  146. package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
  147. package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
  148. package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
  149. package/src/plugins/recon/stages/http-stage.js +89 -0
  150. package/src/plugins/recon/stages/latency-stage.js +148 -0
  151. package/src/plugins/recon/stages/massdns-stage.js +302 -0
  152. package/src/plugins/recon/stages/osint-stage.js +1373 -0
  153. package/src/plugins/recon/stages/ports-stage.js +169 -0
  154. package/src/plugins/recon/stages/screenshot-stage.js +94 -0
  155. package/src/plugins/recon/stages/secrets-stage.js +514 -0
  156. package/src/plugins/recon/stages/subdomains-stage.js +295 -0
  157. package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
  158. package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
  159. package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
  160. package/src/plugins/recon/stages/whois-stage.js +349 -0
  161. package/src/plugins/recon.plugin.js +75 -0
  162. package/src/plugins/recon.plugin.js.backup +2635 -0
  163. package/src/plugins/relation.errors.js +87 -14
  164. package/src/plugins/replicator.plugin.js +514 -137
  165. package/src/plugins/replicators/base-replicator.class.js +89 -1
  166. package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
  167. package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
  168. package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
  169. package/src/plugins/replicators/mysql-replicator.class.js +52 -17
  170. package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
  171. package/src/plugins/replicators/postgres-replicator.class.js +62 -27
  172. package/src/plugins/replicators/s3db-replicator.class.js +25 -18
  173. package/src/plugins/replicators/schema-sync.helper.js +3 -3
  174. package/src/plugins/replicators/sqs-replicator.class.js +8 -2
  175. package/src/plugins/replicators/turso-replicator.class.js +23 -3
  176. package/src/plugins/replicators/webhook-replicator.class.js +42 -4
  177. package/src/plugins/s3-queue.plugin.js +464 -65
  178. package/src/plugins/scheduler.plugin.js +20 -6
  179. package/src/plugins/state-machine.plugin.js +40 -9
  180. package/src/plugins/tfstate/README.md +126 -126
  181. package/src/plugins/tfstate/base-driver.js +28 -4
  182. package/src/plugins/tfstate/errors.js +65 -10
  183. package/src/plugins/tfstate/filesystem-driver.js +52 -8
  184. package/src/plugins/tfstate/index.js +163 -90
  185. package/src/plugins/tfstate/s3-driver.js +64 -6
  186. package/src/plugins/ttl.plugin.js +72 -17
  187. package/src/plugins/vector/distances.js +18 -12
  188. package/src/plugins/vector/kmeans.js +26 -4
  189. package/src/resource.class.js +115 -19
  190. package/src/testing/factory.class.js +20 -3
  191. package/src/testing/seeder.class.js +7 -1
  192. package/src/clients/memory-client.md +0 -917
  193. package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
package/src/errors.js CHANGED
@@ -1,5 +1,25 @@
1
1
  export class BaseError extends Error {
2
- constructor({ verbose, bucket, key, message, code, statusCode, requestId, awsMessage, original, commandName, commandInput, metadata, description, ...rest }) {
2
+ constructor({
3
+ verbose,
4
+ bucket,
5
+ key,
6
+ message,
7
+ code,
8
+ statusCode,
9
+ requestId,
10
+ awsMessage,
11
+ original,
12
+ commandName,
13
+ commandInput,
14
+ metadata,
15
+ description,
16
+ suggestion,
17
+ retriable,
18
+ docs,
19
+ title,
20
+ hint,
21
+ ...rest
22
+ }) {
3
23
  if (verbose) message = message + `\n\nVerbose:\n\n${JSON.stringify(rest, null, 2)}`;
4
24
  super(message);
5
25
 
@@ -15,7 +35,7 @@ export class BaseError extends Error {
15
35
  this.key = key;
16
36
  this.thrownAt = new Date();
17
37
  this.code = code;
18
- this.statusCode = statusCode;
38
+ this.statusCode = statusCode ?? 500;
19
39
  this.requestId = requestId;
20
40
  this.awsMessage = awsMessage;
21
41
  this.original = original;
@@ -23,7 +43,23 @@ export class BaseError extends Error {
23
43
  this.commandInput = commandInput;
24
44
  this.metadata = metadata;
25
45
  this.description = description;
26
- this.data = { bucket, key, ...rest, verbose, message };
46
+ this.suggestion = suggestion;
47
+ this.retriable = retriable ?? false;
48
+ this.docs = docs;
49
+ this.title = title || this.constructor.name;
50
+ this.hint = hint;
51
+ this.data = {
52
+ bucket,
53
+ key,
54
+ ...rest,
55
+ verbose,
56
+ message,
57
+ suggestion: this.suggestion,
58
+ retriable: this.retriable,
59
+ docs: this.docs,
60
+ title: this.title,
61
+ hint: this.hint
62
+ };
27
63
  }
28
64
 
29
65
  toJson() {
@@ -37,6 +73,11 @@ export class BaseError extends Error {
37
73
  bucket: this.bucket,
38
74
  key: this.key,
39
75
  thrownAt: this.thrownAt,
76
+ retriable: this.retriable,
77
+ suggestion: this.suggestion,
78
+ docs: this.docs,
79
+ title: this.title,
80
+ hint: this.hint,
40
81
  commandName: this.commandName,
41
82
  commandInput: this.commandInput,
42
83
  metadata: this.metadata,
@@ -72,54 +113,108 @@ export class S3dbError extends BaseError {
72
113
  // Database operation errors
73
114
  export class DatabaseError extends S3dbError {
74
115
  constructor(message, details = {}) {
75
- super(message, details);
76
- Object.assign(this, details);
116
+ const merged = {
117
+ statusCode: details.statusCode ?? 500,
118
+ retriable: details.retriable ?? false,
119
+ suggestion: details.suggestion ?? 'Check database configuration and ensure the operation parameters are valid.',
120
+ ...details
121
+ };
122
+ super(message, merged);
123
+ Object.assign(this, merged);
77
124
  }
78
125
  }
79
126
 
80
127
  // Validation errors
81
128
  export class ValidationError extends S3dbError {
82
129
  constructor(message, details = {}) {
83
- super(message, details);
84
- Object.assign(this, details);
130
+ const merged = {
131
+ statusCode: details.statusCode ?? 422,
132
+ retriable: details.retriable ?? false,
133
+ suggestion: details.suggestion ?? 'Review validation errors and adjust the request payload before retrying.',
134
+ ...details
135
+ };
136
+ super(message, merged);
137
+ Object.assign(this, merged);
85
138
  }
86
139
  }
87
140
 
88
141
  // Authentication errors
89
142
  export class AuthenticationError extends S3dbError {
90
143
  constructor(message, details = {}) {
91
- super(message, details);
92
- Object.assign(this, details);
144
+ const merged = {
145
+ statusCode: details.statusCode ?? 401,
146
+ retriable: details.retriable ?? false,
147
+ suggestion: details.suggestion ?? 'Provide valid authentication credentials and try again.',
148
+ ...details
149
+ };
150
+ super(message, merged);
151
+ Object.assign(this, merged);
93
152
  }
94
153
  }
95
154
 
96
155
  // Permission/Authorization errors
97
156
  export class PermissionError extends S3dbError {
98
157
  constructor(message, details = {}) {
99
- super(message, details);
100
- Object.assign(this, details);
158
+ const merged = {
159
+ statusCode: details.statusCode ?? 403,
160
+ retriable: details.retriable ?? false,
161
+ suggestion: details.suggestion ?? 'Verify IAM permissions, bucket policies, and credentials before retrying.',
162
+ ...details
163
+ };
164
+ super(message, merged);
165
+ Object.assign(this, merged);
101
166
  }
102
167
  }
103
168
 
104
169
  // Encryption errors
105
170
  export class EncryptionError extends S3dbError {
106
171
  constructor(message, details = {}) {
107
- super(message, details);
108
- Object.assign(this, details);
172
+ const merged = {
173
+ statusCode: details.statusCode ?? 500,
174
+ retriable: details.retriable ?? false,
175
+ suggestion: details.suggestion ?? 'Check encryption keys and inputs. This error generally requires code/config changes before retrying.',
176
+ ...details
177
+ };
178
+ super(message, merged);
179
+ Object.assign(this, merged);
109
180
  }
110
181
  }
111
182
 
112
183
  // Resource not found error
113
184
  export class ResourceNotFound extends S3dbError {
114
185
  constructor({ bucket, resourceName, id, original, ...rest }) {
115
- if (typeof id !== 'string') throw new Error('id must be a string');
116
- if (typeof bucket !== 'string') throw new Error('bucket must be a string');
117
- if (typeof resourceName !== 'string') throw new Error('resourceName must be a string');
186
+ if (typeof id !== 'string') {
187
+ throw new ValidationError('ResourceNotFound requires id to be a string', {
188
+ field: 'id',
189
+ value: id,
190
+ retriable: false,
191
+ suggestion: 'Provide the resource id as a string when constructing ResourceNotFound.'
192
+ });
193
+ }
194
+ if (typeof bucket !== 'string') {
195
+ throw new ValidationError('ResourceNotFound requires bucket to be a string', {
196
+ field: 'bucket',
197
+ value: bucket,
198
+ retriable: false,
199
+ suggestion: 'Provide the bucket name as a string when constructing ResourceNotFound.'
200
+ });
201
+ }
202
+ if (typeof resourceName !== 'string') {
203
+ throw new ValidationError('ResourceNotFound requires resourceName to be a string', {
204
+ field: 'resourceName',
205
+ value: resourceName,
206
+ retriable: false,
207
+ suggestion: 'Provide the resource name as a string when constructing ResourceNotFound.'
208
+ });
209
+ }
118
210
  super(`Resource not found: ${resourceName}/${id} [bucket:${bucket}]`, {
119
211
  bucket,
120
212
  resourceName,
121
213
  id,
122
214
  original,
215
+ statusCode: rest.statusCode ?? 404,
216
+ retriable: rest.retriable ?? false,
217
+ suggestion: rest.suggestion ?? 'Confirm the resource ID and ensure it exists before retrying.',
123
218
  ...rest
124
219
  });
125
220
  }
@@ -127,17 +222,62 @@ export class ResourceNotFound extends S3dbError {
127
222
 
128
223
  export class NoSuchBucket extends S3dbError {
129
224
  constructor({ bucket, original, ...rest }) {
130
- if (typeof bucket !== 'string') throw new Error('bucket must be a string');
131
- super(`Bucket does not exists [bucket:${bucket}]`, { bucket, original, ...rest });
225
+ if (typeof bucket !== 'string') {
226
+ throw new ValidationError('NoSuchBucket requires bucket to be a string', {
227
+ field: 'bucket',
228
+ value: bucket,
229
+ retriable: false,
230
+ suggestion: 'Provide the bucket name as a string when constructing NoSuchBucket.'
231
+ });
232
+ }
233
+ super(`Bucket does not exists [bucket:${bucket}]`, {
234
+ bucket,
235
+ original,
236
+ statusCode: rest.statusCode ?? 404,
237
+ retriable: rest.retriable ?? false,
238
+ suggestion: rest.suggestion ?? 'Verify the bucket name and AWS region. Create the bucket if it is missing.',
239
+ ...rest
240
+ });
132
241
  }
133
242
  }
134
243
 
135
244
  export class NoSuchKey extends S3dbError {
136
245
  constructor({ bucket, key, resourceName, id, original, ...rest }) {
137
- if (typeof key !== 'string') throw new Error('key must be a string');
138
- if (typeof bucket !== 'string') throw new Error('bucket must be a string');
139
- if (id !== undefined && typeof id !== 'string') throw new Error('id must be a string');
140
- super(`No such key: ${key} [bucket:${bucket}]`, { bucket, key, resourceName, id, original, ...rest });
246
+ if (typeof key !== 'string') {
247
+ throw new ValidationError('NoSuchKey requires key to be a string', {
248
+ field: 'key',
249
+ value: key,
250
+ retriable: false,
251
+ suggestion: 'Provide the object key as a string when constructing NoSuchKey.'
252
+ });
253
+ }
254
+ if (typeof bucket !== 'string') {
255
+ throw new ValidationError('NoSuchKey requires bucket to be a string', {
256
+ field: 'bucket',
257
+ value: bucket,
258
+ retriable: false,
259
+ suggestion: 'Provide the bucket name as a string when constructing NoSuchKey.'
260
+ });
261
+ }
262
+ if (id !== undefined && typeof id !== 'string') {
263
+ throw new ValidationError('NoSuchKey requires id to be a string when provided', {
264
+ field: 'id',
265
+ value: id,
266
+ retriable: false,
267
+ suggestion: 'Provide the resource id as a string when including it in NoSuchKey.'
268
+ });
269
+ }
270
+ super(`No such key: ${key} [bucket:${bucket}]`, {
271
+ bucket,
272
+ key,
273
+ resourceName,
274
+ id,
275
+ original,
276
+ statusCode: rest.statusCode ?? 404,
277
+ retriable: rest.retriable ?? false,
278
+ suggestion: rest.suggestion ?? 'Check if the object key is correct and that the object was uploaded.',
279
+ ...rest
280
+ });
141
281
  this.resourceName = resourceName;
142
282
  this.id = id;
143
283
  }
@@ -145,9 +285,33 @@ export class NoSuchKey extends S3dbError {
145
285
 
146
286
  export class NotFound extends S3dbError {
147
287
  constructor({ bucket, key, resourceName, id, original, ...rest }) {
148
- if (typeof key !== 'string') throw new Error('key must be a string');
149
- if (typeof bucket !== 'string') throw new Error('bucket must be a string');
150
- super(`Not found: ${key} [bucket:${bucket}]`, { bucket, key, resourceName, id, original, ...rest });
288
+ if (typeof key !== 'string') {
289
+ throw new ValidationError('NotFound requires key to be a string', {
290
+ field: 'key',
291
+ value: key,
292
+ retriable: false,
293
+ suggestion: 'Provide the object key as a string when constructing NotFound.'
294
+ });
295
+ }
296
+ if (typeof bucket !== 'string') {
297
+ throw new ValidationError('NotFound requires bucket to be a string', {
298
+ field: 'bucket',
299
+ value: bucket,
300
+ retriable: false,
301
+ suggestion: 'Provide the bucket name as a string when constructing NotFound.'
302
+ });
303
+ }
304
+ super(`Not found: ${key} [bucket:${bucket}]`, {
305
+ bucket,
306
+ key,
307
+ resourceName,
308
+ id,
309
+ original,
310
+ statusCode: rest.statusCode ?? 404,
311
+ retriable: rest.retriable ?? false,
312
+ suggestion: rest.suggestion ?? 'Confirm the key and bucket. Upload the object if it is missing.',
313
+ ...rest
314
+ });
151
315
  this.resourceName = resourceName;
152
316
  this.id = id;
153
317
  }
@@ -155,8 +319,22 @@ export class NotFound extends S3dbError {
155
319
 
156
320
  export class MissingMetadata extends S3dbError {
157
321
  constructor({ bucket, original, ...rest }) {
158
- if (typeof bucket !== 'string') throw new Error('bucket must be a string');
159
- super(`Missing metadata for bucket [bucket:${bucket}]`, { bucket, original, ...rest });
322
+ if (typeof bucket !== 'string') {
323
+ throw new ValidationError('MissingMetadata requires bucket to be a string', {
324
+ field: 'bucket',
325
+ value: bucket,
326
+ retriable: false,
327
+ suggestion: 'Provide the bucket name as a string when constructing MissingMetadata.'
328
+ });
329
+ }
330
+ super(`Missing metadata for bucket [bucket:${bucket}]`, {
331
+ bucket,
332
+ original,
333
+ statusCode: rest.statusCode ?? 500,
334
+ retriable: rest.retriable ?? false,
335
+ suggestion: rest.suggestion ?? 'Re-upload metadata or run db.uploadMetadataFile() to regenerate it.',
336
+ ...rest
337
+ });
160
338
  }
161
339
  }
162
340
 
@@ -170,8 +348,22 @@ export class InvalidResourceItem extends S3dbError {
170
348
  original,
171
349
  ...rest
172
350
  }) {
173
- if (typeof bucket !== 'string') throw new Error('bucket must be a string');
174
- if (typeof resourceName !== 'string') throw new Error('resourceName must be a string');
351
+ if (typeof bucket !== 'string') {
352
+ throw new ValidationError('InvalidResourceItem requires bucket to be a string', {
353
+ field: 'bucket',
354
+ value: bucket,
355
+ retriable: false,
356
+ suggestion: 'Provide the bucket name as a string when constructing InvalidResourceItem.'
357
+ });
358
+ }
359
+ if (typeof resourceName !== 'string') {
360
+ throw new ValidationError('InvalidResourceItem requires resourceName to be a string', {
361
+ field: 'resourceName',
362
+ value: resourceName,
363
+ retriable: false,
364
+ suggestion: 'Provide the resource name as a string when constructing InvalidResourceItem.'
365
+ });
366
+ }
175
367
  super(
176
368
  message || `Validation error: This item is not valid. Resource=${resourceName} [bucket:${bucket}].\n${JSON.stringify(validation, null, 2)}`,
177
369
  {
@@ -180,6 +372,9 @@ export class InvalidResourceItem extends S3dbError {
180
372
  attributes,
181
373
  validation,
182
374
  original,
375
+ statusCode: rest.statusCode ?? 422,
376
+ retriable: rest.retriable ?? false,
377
+ suggestion: rest.suggestion ?? 'Fix validation errors on the provided attributes before retrying the request.',
183
378
  ...rest
184
379
  }
185
380
  );
@@ -206,23 +401,63 @@ export function mapAwsError(err, context = {}) {
206
401
  let description;
207
402
  if (code === 'NoSuchKey' || code === 'NotFound') {
208
403
  description = 'The specified key does not exist in the bucket. Check if the key exists and if your credentials have permission to access it.';
209
- return new NoSuchKey({ ...context, original: err, metadata, commandName, commandInput, description });
404
+ return new NoSuchKey({
405
+ ...context,
406
+ original: err,
407
+ metadata,
408
+ commandName,
409
+ commandInput,
410
+ description,
411
+ retriable: false
412
+ });
210
413
  }
211
414
  if (code === 'NoSuchBucket') {
212
415
  description = 'The specified bucket does not exist. Check if the bucket name is correct and if your credentials have permission to access it.';
213
- return new NoSuchBucket({ ...context, original: err, metadata, commandName, commandInput, description });
416
+ return new NoSuchBucket({
417
+ ...context,
418
+ original: err,
419
+ metadata,
420
+ commandName,
421
+ commandInput,
422
+ description,
423
+ retriable: false
424
+ });
214
425
  }
215
426
  if (code === 'AccessDenied' || (err.statusCode === 403) || code === 'Forbidden') {
216
427
  description = 'Access denied. Check your AWS credentials, IAM permissions, and bucket policy.';
217
- return new PermissionError('Access denied', { ...context, original: err, metadata, commandName, commandInput, description });
428
+ return new PermissionError('Access denied', {
429
+ ...context,
430
+ original: err,
431
+ metadata,
432
+ commandName,
433
+ commandInput,
434
+ description,
435
+ retriable: false
436
+ });
218
437
  }
219
438
  if (code === 'ValidationError' || (err.statusCode === 400)) {
220
439
  description = 'Validation error. Check the request parameters and payload format.';
221
- return new ValidationError('Validation error', { ...context, original: err, metadata, commandName, commandInput, description });
440
+ return new ValidationError('Validation error', {
441
+ ...context,
442
+ original: err,
443
+ metadata,
444
+ commandName,
445
+ commandInput,
446
+ description,
447
+ retriable: false
448
+ });
222
449
  }
223
450
  if (code === 'MissingMetadata') {
224
451
  description = 'Object metadata is missing or invalid. Check if the object was uploaded correctly.';
225
- return new MissingMetadata({ ...context, original: err, metadata, commandName, commandInput, description });
452
+ return new MissingMetadata({
453
+ ...context,
454
+ original: err,
455
+ metadata,
456
+ commandName,
457
+ commandInput,
458
+ description,
459
+ retriable: false
460
+ });
226
461
  }
227
462
  // Outros mapeamentos podem ser adicionados aqui
228
463
  // Incluir detalhes do erro original para facilitar debug
@@ -234,35 +469,71 @@ export function mapAwsError(err, context = {}) {
234
469
  ].filter(Boolean).join(' | ');
235
470
 
236
471
  description = `Check the error details and AWS documentation. Original error: ${err.message || err.toString()}`;
237
- return new UnknownError(errorDetails, { ...context, original: err, metadata, commandName, commandInput, description });
472
+ return new UnknownError(errorDetails, {
473
+ ...context,
474
+ original: err,
475
+ metadata,
476
+ commandName,
477
+ commandInput,
478
+ description,
479
+ retriable: context.retriable ?? false
480
+ });
238
481
  }
239
482
 
240
483
  export class ConnectionStringError extends S3dbError {
241
484
  constructor(message, details = {}) {
242
485
  const description = details.description || 'Invalid connection string format. Check the connection string syntax and credentials.';
243
- super(message, { ...details, description });
486
+ const merged = {
487
+ statusCode: details.statusCode ?? 400,
488
+ retriable: details.retriable ?? false,
489
+ suggestion: details.suggestion ?? 'Fix the connection string and retry the operation.',
490
+ description,
491
+ ...details
492
+ };
493
+ super(message, merged);
244
494
  }
245
495
  }
246
496
 
247
497
  export class CryptoError extends S3dbError {
248
498
  constructor(message, details = {}) {
249
499
  const description = details.description || 'Cryptography operation failed. Check if the crypto library is available and input is valid.';
250
- super(message, { ...details, description });
500
+ const merged = {
501
+ statusCode: details.statusCode ?? 500,
502
+ retriable: details.retriable ?? false,
503
+ suggestion: details.suggestion ?? 'Validate crypto inputs and environment setup before retrying.',
504
+ description,
505
+ ...details
506
+ };
507
+ super(message, merged);
251
508
  }
252
509
  }
253
510
 
254
511
  export class SchemaError extends S3dbError {
255
512
  constructor(message, details = {}) {
256
513
  const description = details.description || 'Schema validation failed. Check schema definition and input data format.';
257
- super(message, { ...details, description });
514
+ const merged = {
515
+ statusCode: details.statusCode ?? 400,
516
+ retriable: details.retriable ?? false,
517
+ suggestion: details.suggestion ?? 'Update the schema or adjust the data to match the schema definition.',
518
+ description,
519
+ ...details
520
+ };
521
+ super(message, merged);
258
522
  }
259
523
  }
260
524
 
261
525
  export class ResourceError extends S3dbError {
262
526
  constructor(message, details = {}) {
263
527
  const description = details.description || 'Resource operation failed. Check resource configuration, attributes, and operation context.';
264
- super(message, { ...details, description });
265
- Object.assign(this, details);
528
+ const merged = {
529
+ statusCode: details.statusCode ?? 400,
530
+ retriable: details.retriable ?? false,
531
+ suggestion: details.suggestion ?? 'Review the resource configuration and request payload before retrying.',
532
+ description,
533
+ ...details
534
+ };
535
+ super(message, merged);
536
+ Object.assign(this, merged);
266
537
  }
267
538
  }
268
539
 
@@ -300,6 +571,8 @@ Docs: https://github.com/forattini-dev/s3db.js/blob/main/docs/README.md#partitio
300
571
 
301
572
  super(message, {
302
573
  ...details,
574
+ statusCode: details.statusCode ?? 400,
575
+ retriable: details.retriable ?? false,
303
576
  description
304
577
  });
305
578
  }
@@ -374,6 +647,8 @@ Docs: https://github.com/forattini-dev/s3db.js/blob/main/docs/plugins/eventual-c
374
647
  configuredResources,
375
648
  registeredResources,
376
649
  pluginInitialized,
650
+ statusCode: rest.statusCode ?? 400,
651
+ retriable: rest.retriable ?? false,
377
652
  description
378
653
  });
379
654
  }
@@ -418,12 +693,17 @@ Docs: https://github.com/forattini-dev/s3db.js/blob/main/docs/plugins/README.md
418
693
  `.trim();
419
694
  }
420
695
 
421
- super(message, {
696
+ const merged = {
422
697
  ...rest,
423
698
  pluginName,
424
699
  operation,
700
+ statusCode: rest.statusCode ?? 500,
701
+ retriable: rest.retriable ?? false,
425
702
  description
426
- });
703
+ };
704
+
705
+ super(message, merged);
706
+ Object.assign(this, merged);
427
707
  }
428
708
  }
429
709
 
@@ -464,6 +744,8 @@ Docs: https://github.com/forattini-dev/s3db.js/blob/main/docs/plugins/README.md#
464
744
  pluginSlug,
465
745
  key,
466
746
  operation,
747
+ statusCode: rest.statusCode ?? 500,
748
+ retriable: rest.retriable ?? false,
467
749
  description
468
750
  });
469
751
  }
@@ -516,6 +798,8 @@ Check driver configuration and permissions.
516
798
  operation,
517
799
  queueSize,
518
800
  maxQueueSize,
801
+ statusCode: rest.statusCode ?? 503,
802
+ retriable: rest.retriable ?? (queueSize >= maxQueueSize),
519
803
  description
520
804
  });
521
805
  }
@@ -553,6 +837,8 @@ Docs: https://github.com/forattini-dev/s3db.js/blob/main/docs/README.md#behavior
553
837
  ...rest,
554
838
  behavior,
555
839
  availableBehaviors,
840
+ statusCode: rest.statusCode ?? 400,
841
+ retriable: rest.retriable ?? false,
556
842
  description
557
843
  });
558
844
  }
@@ -591,6 +877,8 @@ Docs: https://github.com/forattini-dev/s3db.js/blob/main/docs/README.md#streamin
591
877
  ...rest,
592
878
  operation,
593
879
  resource,
880
+ statusCode: rest.statusCode ?? 500,
881
+ retriable: rest.retriable ?? false,
594
882
  description
595
883
  });
596
884
  }
@@ -649,6 +937,8 @@ Docs: https://github.com/forattini-dev/s3db.js/blob/main/docs/README.md#metadata
649
937
  excess,
650
938
  resourceName,
651
939
  operation,
940
+ statusCode: rest.statusCode ?? 413,
941
+ retriable: rest.retriable ?? false,
652
942
  description
653
943
  });
654
944
  }