s3db.js 6.2.0 → 7.0.1

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 (60) hide show
  1. package/PLUGINS.md +2724 -0
  2. package/README.md +372 -469
  3. package/UNLICENSE +24 -0
  4. package/dist/s3db.cjs.js +12105 -19396
  5. package/dist/s3db.cjs.min.js +1 -1
  6. package/dist/s3db.d.ts +373 -72
  7. package/dist/s3db.es.js +12090 -19393
  8. package/dist/s3db.es.min.js +1 -1
  9. package/dist/s3db.iife.js +12103 -19398
  10. package/dist/s3db.iife.min.js +1 -1
  11. package/package.json +44 -38
  12. package/src/behaviors/body-only.js +110 -0
  13. package/src/behaviors/body-overflow.js +153 -0
  14. package/src/behaviors/enforce-limits.js +195 -0
  15. package/src/behaviors/index.js +39 -0
  16. package/src/behaviors/truncate-data.js +204 -0
  17. package/src/behaviors/user-managed.js +147 -0
  18. package/src/client.class.js +515 -0
  19. package/src/concerns/base62.js +61 -0
  20. package/src/concerns/calculator.js +204 -0
  21. package/src/concerns/crypto.js +159 -0
  22. package/src/concerns/id.js +8 -0
  23. package/src/concerns/index.js +5 -0
  24. package/src/concerns/try-fn.js +151 -0
  25. package/src/connection-string.class.js +75 -0
  26. package/src/database.class.js +599 -0
  27. package/src/errors.js +261 -0
  28. package/src/index.js +17 -0
  29. package/src/plugins/audit.plugin.js +442 -0
  30. package/src/plugins/cache/cache.class.js +53 -0
  31. package/src/plugins/cache/index.js +6 -0
  32. package/src/plugins/cache/memory-cache.class.js +164 -0
  33. package/src/plugins/cache/s3-cache.class.js +189 -0
  34. package/src/plugins/cache.plugin.js +275 -0
  35. package/src/plugins/consumers/index.js +24 -0
  36. package/src/plugins/consumers/rabbitmq-consumer.js +56 -0
  37. package/src/plugins/consumers/sqs-consumer.js +102 -0
  38. package/src/plugins/costs.plugin.js +81 -0
  39. package/src/plugins/fulltext.plugin.js +473 -0
  40. package/src/plugins/index.js +12 -0
  41. package/src/plugins/metrics.plugin.js +603 -0
  42. package/src/plugins/plugin.class.js +210 -0
  43. package/src/plugins/plugin.obj.js +13 -0
  44. package/src/plugins/queue-consumer.plugin.js +134 -0
  45. package/src/plugins/replicator.plugin.js +769 -0
  46. package/src/plugins/replicators/base-replicator.class.js +85 -0
  47. package/src/plugins/replicators/bigquery-replicator.class.js +328 -0
  48. package/src/plugins/replicators/index.js +44 -0
  49. package/src/plugins/replicators/postgres-replicator.class.js +427 -0
  50. package/src/plugins/replicators/s3db-replicator.class.js +352 -0
  51. package/src/plugins/replicators/sqs-replicator.class.js +427 -0
  52. package/src/resource.class.js +2626 -0
  53. package/src/s3db.d.ts +1263 -0
  54. package/src/schema.class.js +706 -0
  55. package/src/stream/index.js +16 -0
  56. package/src/stream/resource-ids-page-reader.class.js +10 -0
  57. package/src/stream/resource-ids-reader.class.js +63 -0
  58. package/src/stream/resource-reader.class.js +81 -0
  59. package/src/stream/resource-writer.class.js +92 -0
  60. package/src/validator.class.js +97 -0
package/src/errors.js ADDED
@@ -0,0 +1,261 @@
1
+ export class BaseError extends Error {
2
+ constructor({ verbose, bucket, key, message, code, statusCode, requestId, awsMessage, original, commandName, commandInput, metadata, suggestion, ...rest }) {
3
+ if (verbose) message = message + `\n\nVerbose:\n\n${JSON.stringify(rest, null, 2)}`;
4
+ super(message);
5
+
6
+ if (typeof Error.captureStackTrace === 'function') {
7
+ Error.captureStackTrace(this, this.constructor);
8
+ } else {
9
+ this.stack = (new Error(message)).stack;
10
+ }
11
+
12
+ super.name = this.constructor.name;
13
+ this.name = this.constructor.name;
14
+ this.bucket = bucket;
15
+ this.key = key;
16
+ this.thrownAt = new Date();
17
+ this.code = code;
18
+ this.statusCode = statusCode;
19
+ this.requestId = requestId;
20
+ this.awsMessage = awsMessage;
21
+ this.original = original;
22
+ this.commandName = commandName;
23
+ this.commandInput = commandInput;
24
+ this.metadata = metadata;
25
+ this.suggestion = suggestion;
26
+ this.data = { bucket, key, ...rest, verbose, message };
27
+ }
28
+
29
+ toJson() {
30
+ return {
31
+ name: this.name,
32
+ message: this.message,
33
+ code: this.code,
34
+ statusCode: this.statusCode,
35
+ requestId: this.requestId,
36
+ awsMessage: this.awsMessage,
37
+ bucket: this.bucket,
38
+ key: this.key,
39
+ thrownAt: this.thrownAt,
40
+ commandName: this.commandName,
41
+ commandInput: this.commandInput,
42
+ metadata: this.metadata,
43
+ suggestion: this.suggestion,
44
+ data: this.data,
45
+ original: this.original,
46
+ stack: this.stack,
47
+ };
48
+ }
49
+
50
+ toString() {
51
+ return `${this.name} | ${this.message}`;
52
+ }
53
+ }
54
+
55
+ // Base error class for S3DB
56
+ export class S3dbError extends BaseError {
57
+ constructor(message, details = {}) {
58
+ // Extrai campos AWS se presentes
59
+ let code, statusCode, requestId, awsMessage, original, metadata;
60
+ if (details.original) {
61
+ original = details.original;
62
+ code = original.code || original.Code || original.name;
63
+ statusCode = original.statusCode || (original.$metadata && original.$metadata.httpStatusCode);
64
+ requestId = original.requestId || (original.$metadata && original.$metadata.requestId);
65
+ awsMessage = original.message;
66
+ metadata = original.$metadata ? { ...original.$metadata } : undefined;
67
+ }
68
+ super({ message, ...details, code, statusCode, requestId, awsMessage, original, metadata });
69
+ }
70
+ }
71
+
72
+ // Database operation errors
73
+ export class DatabaseError extends S3dbError {
74
+ constructor(message, details = {}) {
75
+ super(message, details);
76
+ Object.assign(this, details);
77
+ }
78
+ }
79
+
80
+ // Validation errors
81
+ export class ValidationError extends S3dbError {
82
+ constructor(message, details = {}) {
83
+ super(message, details);
84
+ Object.assign(this, details);
85
+ }
86
+ }
87
+
88
+ // Authentication errors
89
+ export class AuthenticationError extends S3dbError {
90
+ constructor(message, details = {}) {
91
+ super(message, details);
92
+ Object.assign(this, details);
93
+ }
94
+ }
95
+
96
+ // Permission/Authorization errors
97
+ export class PermissionError extends S3dbError {
98
+ constructor(message, details = {}) {
99
+ super(message, details);
100
+ Object.assign(this, details);
101
+ }
102
+ }
103
+
104
+ // Encryption errors
105
+ export class EncryptionError extends S3dbError {
106
+ constructor(message, details = {}) {
107
+ super(message, details);
108
+ Object.assign(this, details);
109
+ }
110
+ }
111
+
112
+ // Resource not found error
113
+ export class ResourceNotFound extends S3dbError {
114
+ 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');
118
+ super(`Resource not found: ${resourceName}/${id} [bucket:${bucket}]`, {
119
+ bucket,
120
+ resourceName,
121
+ id,
122
+ original,
123
+ ...rest
124
+ });
125
+ }
126
+ }
127
+
128
+ export class NoSuchBucket extends S3dbError {
129
+ 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 });
132
+ }
133
+ }
134
+
135
+ export class NoSuchKey extends S3dbError {
136
+ 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 });
141
+ this.resourceName = resourceName;
142
+ this.id = id;
143
+ }
144
+ }
145
+
146
+ export class NotFound extends S3dbError {
147
+ 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 });
151
+ this.resourceName = resourceName;
152
+ this.id = id;
153
+ }
154
+ }
155
+
156
+ export class MissingMetadata extends S3dbError {
157
+ 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 });
160
+ }
161
+ }
162
+
163
+ export class InvalidResourceItem extends S3dbError {
164
+ constructor({
165
+ bucket,
166
+ resourceName,
167
+ attributes,
168
+ validation,
169
+ message,
170
+ original,
171
+ ...rest
172
+ }) {
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');
175
+ super(
176
+ message || `Validation error: This item is not valid. Resource=${resourceName} [bucket:${bucket}].\n${JSON.stringify(validation, null, 2)}`,
177
+ {
178
+ bucket,
179
+ resourceName,
180
+ attributes,
181
+ validation,
182
+ original,
183
+ ...rest
184
+ }
185
+ );
186
+ }
187
+ }
188
+
189
+ export class UnknownError extends S3dbError {}
190
+
191
+ export const ErrorMap = {
192
+ 'NotFound': NotFound,
193
+ 'NoSuchKey': NoSuchKey,
194
+ 'UnknownError': UnknownError,
195
+ 'NoSuchBucket': NoSuchBucket,
196
+ 'MissingMetadata': MissingMetadata,
197
+ 'InvalidResourceItem': InvalidResourceItem,
198
+ };
199
+
200
+ // Utilitário para mapear erro AWS para erro customizado
201
+ export function mapAwsError(err, context = {}) {
202
+ const code = err.code || err.Code || err.name;
203
+ const metadata = err.$metadata ? { ...err.$metadata } : undefined;
204
+ const commandName = context.commandName;
205
+ const commandInput = context.commandInput;
206
+ let suggestion;
207
+ if (code === 'NoSuchKey' || code === 'NotFound') {
208
+ suggestion = 'Check if the key exists in the specified bucket and if your credentials have permission.';
209
+ return new NoSuchKey({ ...context, original: err, metadata, commandName, commandInput, suggestion });
210
+ }
211
+ if (code === 'NoSuchBucket') {
212
+ suggestion = 'Check if the bucket exists and if your credentials have permission.';
213
+ return new NoSuchBucket({ ...context, original: err, metadata, commandName, commandInput, suggestion });
214
+ }
215
+ if (code === 'AccessDenied' || (err.statusCode === 403) || code === 'Forbidden') {
216
+ suggestion = 'Check your credentials and bucket policy.';
217
+ return new PermissionError('Access denied', { ...context, original: err, metadata, commandName, commandInput, suggestion });
218
+ }
219
+ if (code === 'ValidationError' || (err.statusCode === 400)) {
220
+ suggestion = 'Check the request parameters and payload.';
221
+ return new ValidationError('Validation error', { ...context, original: err, metadata, commandName, commandInput, suggestion });
222
+ }
223
+ if (code === 'MissingMetadata') {
224
+ suggestion = 'Check if the object metadata is present and valid.';
225
+ return new MissingMetadata({ ...context, original: err, metadata, commandName, commandInput, suggestion });
226
+ }
227
+ // Outros mapeamentos podem ser adicionados aqui
228
+ suggestion = 'Check the error details and AWS documentation.';
229
+ return new UnknownError('Unknown error', { ...context, original: err, metadata, commandName, commandInput, suggestion });
230
+ }
231
+
232
+ export class ConnectionStringError extends S3dbError {
233
+ constructor(message, details = {}) {
234
+ super(message, { ...details, suggestion: 'Check the connection string format and credentials.' });
235
+ }
236
+ }
237
+
238
+ export class CryptoError extends S3dbError {
239
+ constructor(message, details = {}) {
240
+ super(message, { ...details, suggestion: 'Check if the crypto library is available and input is valid.' });
241
+ }
242
+ }
243
+
244
+ export class SchemaError extends S3dbError {
245
+ constructor(message, details = {}) {
246
+ super(message, { ...details, suggestion: 'Check schema definition and input data.' });
247
+ }
248
+ }
249
+
250
+ export class ResourceError extends S3dbError {
251
+ constructor(message, details = {}) {
252
+ super(message, { ...details, suggestion: details.suggestion || 'Check resource configuration, attributes, and operation context.' });
253
+ Object.assign(this, details);
254
+ }
255
+ }
256
+
257
+ export class PartitionError extends S3dbError {
258
+ constructor(message, details = {}) {
259
+ super(message, { ...details, suggestion: details.suggestion || 'Check partition definition, fields, and input values.' });
260
+ }
261
+ }
package/src/index.js ADDED
@@ -0,0 +1,17 @@
1
+ // directories
2
+ export * from './behaviors/index.js'
3
+ export * from './concerns/index.js'
4
+ export * from './plugins/index.js'
5
+ export * from './stream/index.js'
6
+
7
+ // single
8
+ export * from './client.class.js'
9
+ export * from './connection-string.class.js'
10
+ export * from './database.class.js'
11
+ export * from './errors.js'
12
+ export * from './resource.class.js'
13
+ export * from './schema.class.js'
14
+ export * from './validator.class.js'
15
+
16
+ // default
17
+ export { S3db as default } from './database.class.js'