s3db.js 13.1.0 → 13.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s3db.js",
3
- "version": "13.1.0",
3
+ "version": "13.2.2",
4
4
  "description": "Use AWS S3, the world's most reliable document storage, as a database with this ORM.",
5
5
  "main": "dist/s3db.cjs.js",
6
6
  "module": "dist/s3db.es.js",
@@ -133,6 +133,7 @@
133
133
  "@rollup/plugin-node-resolve": "^16.0.3",
134
134
  "@rollup/plugin-replace": "^6.0.2",
135
135
  "@rollup/plugin-terser": "^0.4.4",
136
+ "@tensorflow/tfjs-node": "^4.22.0",
136
137
  "@types/node": "24.7.0",
137
138
  "@xenova/transformers": "^2.17.2",
138
139
  "@yao-pkg/pkg": "^6.9.0",
@@ -73,7 +73,7 @@ export class MemoryClient extends EventEmitter {
73
73
  const commandName = command.constructor.name;
74
74
  const input = command.input || {};
75
75
 
76
- this.emit('command.request', commandName, input);
76
+ this.emit('cl:request', commandName, input);
77
77
 
78
78
  let response;
79
79
 
@@ -105,7 +105,7 @@ export class MemoryClient extends EventEmitter {
105
105
  throw new Error(`Unsupported command: ${commandName}`);
106
106
  }
107
107
 
108
- this.emit('command.response', commandName, response, input);
108
+ this.emit('cl:response', commandName, response, input);
109
109
  return response;
110
110
 
111
111
  } catch (error) {
@@ -237,7 +237,7 @@ export class MemoryClient extends EventEmitter {
237
237
  ifMatch
238
238
  });
239
239
 
240
- this.emit('putObject', null, { key, metadata, contentType, body, contentEncoding, contentLength });
240
+ this.emit('cl:PutObject', null, { key, metadata, contentType, body, contentEncoding, contentLength });
241
241
 
242
242
  return response;
243
243
  }
@@ -257,7 +257,7 @@ export class MemoryClient extends EventEmitter {
257
257
  }
258
258
  }
259
259
 
260
- this.emit('getObject', null, { key });
260
+ this.emit('cl:GetObject', null, { key });
261
261
 
262
262
  return {
263
263
  ...response,
@@ -280,7 +280,7 @@ export class MemoryClient extends EventEmitter {
280
280
  }
281
281
  }
282
282
 
283
- this.emit('headObject', null, { key });
283
+ this.emit('cl:HeadObject', null, { key });
284
284
 
285
285
  return {
286
286
  ...response,
@@ -311,7 +311,7 @@ export class MemoryClient extends EventEmitter {
311
311
  contentType
312
312
  });
313
313
 
314
- this.emit('copyObject', null, { from, to, metadata, metadataDirective });
314
+ this.emit('cl:CopyObject', null, { from, to, metadata, metadataDirective });
315
315
 
316
316
  return response;
317
317
  }
@@ -331,7 +331,7 @@ export class MemoryClient extends EventEmitter {
331
331
  const fullKey = this.keyPrefix ? path.join(this.keyPrefix, key) : key;
332
332
  const response = await this.storage.delete(fullKey);
333
333
 
334
- this.emit('deleteObject', null, { key });
334
+ this.emit('cl:DeleteObject', null, { key });
335
335
 
336
336
  return response;
337
337
  }
@@ -380,7 +380,7 @@ export class MemoryClient extends EventEmitter {
380
380
  continuationToken
381
381
  });
382
382
 
383
- this.emit('listObjects', null, { prefix, count: response.Contents.length });
383
+ this.emit('cl:ListObjects', null, { prefix, count: response.Contents.length });
384
384
 
385
385
  return response;
386
386
  }
@@ -431,7 +431,7 @@ export class MemoryClient extends EventEmitter {
431
431
  .map(x => (x.startsWith('/') ? x.replace('/', '') : x));
432
432
  }
433
433
 
434
- this.emit('getKeysPage', keys, params);
434
+ this.emit('cl:GetKeysPage', keys, params);
435
435
  return keys;
436
436
  }
437
437
 
@@ -454,7 +454,7 @@ export class MemoryClient extends EventEmitter {
454
454
  .map(x => (x.startsWith('/') ? x.replace('/', '') : x));
455
455
  }
456
456
 
457
- this.emit('getAllKeys', keys, { prefix });
457
+ this.emit('cl:GetAllKeys', keys, { prefix });
458
458
  return keys;
459
459
  }
460
460
 
@@ -464,7 +464,7 @@ export class MemoryClient extends EventEmitter {
464
464
  async count({ prefix = '' } = {}) {
465
465
  const keys = await this.getAllKeys({ prefix });
466
466
  const count = keys.length;
467
- this.emit('count', count, { prefix });
467
+ this.emit('cl:Count', count, { prefix });
468
468
  return count;
469
469
  }
470
470
 
@@ -479,14 +479,14 @@ export class MemoryClient extends EventEmitter {
479
479
  const result = await this.deleteObjects(keys);
480
480
  totalDeleted = result.Deleted.length;
481
481
 
482
- this.emit('deleteAll', {
482
+ this.emit('cl:DeleteAll', {
483
483
  prefix,
484
484
  batch: totalDeleted,
485
485
  total: totalDeleted
486
486
  });
487
487
  }
488
488
 
489
- this.emit('deleteAllComplete', {
489
+ this.emit('cl:DeleteAllComplete', {
490
490
  prefix,
491
491
  totalDeleted
492
492
  });
@@ -504,13 +504,13 @@ export class MemoryClient extends EventEmitter {
504
504
 
505
505
  // If offset is beyond available keys, return null
506
506
  if (offset >= keys.length) {
507
- this.emit('getContinuationTokenAfterOffset', null, { prefix, offset });
507
+ this.emit('cl:GetContinuationTokenAfterOffset', null, { prefix, offset });
508
508
  return null;
509
509
  }
510
510
 
511
511
  // Return the key at offset position as continuation token
512
512
  const token = keys[offset];
513
- this.emit('getContinuationTokenAfterOffset', token, { prefix, offset });
513
+ this.emit('cl:GetContinuationTokenAfterOffset', token, { prefix, offset });
514
514
  return token;
515
515
  }
516
516
 
@@ -544,7 +544,7 @@ export class MemoryClient extends EventEmitter {
544
544
  }
545
545
  }
546
546
 
547
- this.emit('moveAllObjects', { results, errors }, { prefixFrom, prefixTo });
547
+ this.emit('cl:MoveAllObjects', { results, errors }, { prefixFrom, prefixTo });
548
548
 
549
549
  if (errors.length > 0) {
550
550
  const error = new Error('Some objects could not be moved');
@@ -100,7 +100,7 @@ export class S3Client extends EventEmitter {
100
100
  }
101
101
 
102
102
  async sendCommand(command) {
103
- this.emit("command.request", command.constructor.name, command.input);
103
+ this.emit("cl:request", command.constructor.name, command.input);
104
104
  const [ok, err, response] = await tryFn(() => this.client.send(command));
105
105
  if (!ok) {
106
106
  const bucket = this.config.bucket;
@@ -112,7 +112,7 @@ export class S3Client extends EventEmitter {
112
112
  commandInput: command.input,
113
113
  });
114
114
  }
115
- this.emit("command.response", command.constructor.name, response, command.input);
115
+ this.emit("cl:response", command.constructor.name, response, command.input);
116
116
  return response;
117
117
  }
118
118
 
@@ -146,7 +146,7 @@ export class S3Client extends EventEmitter {
146
146
  if (ifMatch !== undefined) options.IfMatch = ifMatch
147
147
 
148
148
  const [ok, err, response] = await tryFn(() => this.sendCommand(new PutObjectCommand(options)));
149
- this.emit('putObject', err || response, { key, metadata, contentType, body, contentEncoding, contentLength });
149
+ this.emit('cl:PutObject', err || response, { key, metadata, contentType, body, contentEncoding, contentLength });
150
150
 
151
151
  if (!ok) {
152
152
  throw mapAwsError(err, {
@@ -182,7 +182,7 @@ export class S3Client extends EventEmitter {
182
182
  return res;
183
183
  });
184
184
 
185
- this.emit('getObject', err || response, { key });
185
+ this.emit('cl:GetObject', err || response, { key });
186
186
 
187
187
  if (!ok) {
188
188
  throw mapAwsError(err, {
@@ -218,7 +218,7 @@ export class S3Client extends EventEmitter {
218
218
  return res;
219
219
  });
220
220
 
221
- this.emit('headObject', err || response, { key });
221
+ this.emit('cl:HeadObject', err || response, { key });
222
222
 
223
223
  if (!ok) {
224
224
  throw mapAwsError(err, {
@@ -261,7 +261,7 @@ export class S3Client extends EventEmitter {
261
261
  }
262
262
 
263
263
  const [ok, err, response] = await tryFn(() => this.sendCommand(new CopyObjectCommand(options)));
264
- this.emit('copyObject', err || response, { from, to, metadataDirective });
264
+ this.emit('cl:CopyObject', err || response, { from, to, metadataDirective });
265
265
 
266
266
  if (!ok) {
267
267
  throw mapAwsError(err, {
@@ -291,7 +291,7 @@ export class S3Client extends EventEmitter {
291
291
  };
292
292
 
293
293
  const [ok, err, response] = await tryFn(() => this.sendCommand(new DeleteObjectCommand(options)));
294
- this.emit('deleteObject', err || response, { key });
294
+ this.emit('cl:DeleteObject', err || response, { key });
295
295
 
296
296
  if (!ok) {
297
297
  throw mapAwsError(err, {
@@ -346,7 +346,7 @@ export class S3Client extends EventEmitter {
346
346
  notFound: errors,
347
347
  }
348
348
 
349
- this.emit("deleteObjects", report, keys);
349
+ this.emit("cl:DeleteObjects", report, keys);
350
350
  return report;
351
351
  }
352
352
 
@@ -382,7 +382,7 @@ export class S3Client extends EventEmitter {
382
382
  const deletedCount = deleteResponse.Deleted ? deleteResponse.Deleted.length : 0;
383
383
  totalDeleted += deletedCount;
384
384
 
385
- this.emit("deleteAll", {
385
+ this.emit("cl:DeleteAll", {
386
386
  prefix,
387
387
  batch: deletedCount,
388
388
  total: totalDeleted
@@ -392,7 +392,7 @@ export class S3Client extends EventEmitter {
392
392
  continuationToken = listResponse.IsTruncated ? listResponse.NextContinuationToken : undefined;
393
393
  } while (continuationToken);
394
394
 
395
- this.emit("deleteAllComplete", {
395
+ this.emit("cl:DeleteAllComplete", {
396
396
  prefix,
397
397
  totalDeleted
398
398
  });
@@ -428,7 +428,7 @@ export class S3Client extends EventEmitter {
428
428
  if (!ok) {
429
429
  throw new UnknownError("Unknown error in listObjects", { prefix, bucket: this.config.bucket, original: err });
430
430
  }
431
- this.emit("listObjects", response, options);
431
+ this.emit("cl:ListObjects", response, options);
432
432
  return response;
433
433
  }
434
434
 
@@ -446,7 +446,7 @@ export class S3Client extends EventEmitter {
446
446
  truncated = response.IsTruncated || false;
447
447
  continuationToken = response.NextContinuationToken;
448
448
  }
449
- this.emit("count", count, { prefix });
449
+ this.emit("cl:Count", count, { prefix });
450
450
  return count;
451
451
  }
452
452
 
@@ -471,7 +471,7 @@ export class S3Client extends EventEmitter {
471
471
  .map((x) => x.replace(this.config.keyPrefix, ""))
472
472
  .map((x) => (x.startsWith("/") ? x.replace(`/`, "") : x));
473
473
  }
474
- this.emit("getAllKeys", keys, { prefix });
474
+ this.emit("cl:GetAllKeys", keys, { prefix });
475
475
  return keys;
476
476
  }
477
477
 
@@ -506,7 +506,7 @@ export class S3Client extends EventEmitter {
506
506
  break;
507
507
  }
508
508
  }
509
- this.emit("getContinuationTokenAfterOffset", continuationToken || null, params);
509
+ this.emit("cl:GetContinuationTokenAfterOffset", continuationToken || null, params);
510
510
  return continuationToken || null;
511
511
  }
512
512
 
@@ -525,7 +525,7 @@ export class S3Client extends EventEmitter {
525
525
  offset,
526
526
  });
527
527
  if (!continuationToken) {
528
- this.emit("getKeysPage", [], params);
528
+ this.emit("cl:GetKeysPage", [], params);
529
529
  return [];
530
530
  }
531
531
  }
@@ -550,7 +550,7 @@ export class S3Client extends EventEmitter {
550
550
  .map((x) => x.replace(this.config.keyPrefix, ""))
551
551
  .map((x) => (x.startsWith("/") ? x.replace(`/`, "") : x));
552
552
  }
553
- this.emit("getKeysPage", keys, params);
553
+ this.emit("cl:GetKeysPage", keys, params);
554
554
  return keys;
555
555
  }
556
556
 
@@ -572,7 +572,7 @@ export class S3Client extends EventEmitter {
572
572
  }
573
573
  return to;
574
574
  });
575
- this.emit("moveAllObjects", { results, errors }, { prefixFrom, prefixTo });
575
+ this.emit("cl:MoveAllObjects", { results, errors }, { prefixFrom, prefixTo });
576
576
  if (errors.length > 0) {
577
577
  throw new UnknownError("Some objects could not be moved", {
578
578
  bucket: this.config.bucket,
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Error Classifier - Determines if errors should be retried
3
+ *
4
+ * Classifies errors into RETRIABLE or NON_RETRIABLE categories
5
+ * based on error codes, HTTP status codes, and error properties.
6
+ *
7
+ * @example
8
+ * const classification = ErrorClassifier.classify(error);
9
+ * if (classification === 'RETRIABLE') {
10
+ * // Retry the operation
11
+ * }
12
+ */
13
+
14
+ const RETRIABLE = 'RETRIABLE';
15
+ const NON_RETRIABLE = 'NON_RETRIABLE';
16
+
17
+ /**
18
+ * Network and timeout error codes (retriable)
19
+ */
20
+ const RETRIABLE_NETWORK_CODES = new Set([
21
+ 'ECONNREFUSED',
22
+ 'ETIMEDOUT',
23
+ 'ECONNRESET',
24
+ 'EPIPE',
25
+ 'ENOTFOUND',
26
+ 'NetworkError',
27
+ 'NETWORK_ERROR',
28
+ 'TimeoutError',
29
+ 'TIMEOUT'
30
+ ]);
31
+
32
+ /**
33
+ * AWS throttling and rate limit codes (retriable)
34
+ */
35
+ const RETRIABLE_AWS_CODES = new Set([
36
+ 'ThrottlingException',
37
+ 'TooManyRequestsException',
38
+ 'RequestLimitExceeded',
39
+ 'ProvisionedThroughputExceededException',
40
+ 'RequestThrottledException',
41
+ 'SlowDown',
42
+ 'ServiceUnavailable'
43
+ ]);
44
+
45
+ /**
46
+ * AWS conflict and conditional check failures (retriable)
47
+ */
48
+ const RETRIABLE_AWS_CONFLICTS = new Set([
49
+ 'ConditionalCheckFailedException',
50
+ 'TransactionConflictException'
51
+ ]);
52
+
53
+ /**
54
+ * Retriable HTTP status codes (5xx server errors, 429 rate limit)
55
+ */
56
+ const RETRIABLE_STATUS_CODES = new Set([
57
+ 429, // Too Many Requests
58
+ 500, // Internal Server Error
59
+ 502, // Bad Gateway
60
+ 503, // Service Unavailable
61
+ 504, // Gateway Timeout
62
+ 507, // Insufficient Storage
63
+ 509 // Bandwidth Limit Exceeded
64
+ ]);
65
+
66
+ /**
67
+ * Non-retriable error names (validation, business logic)
68
+ */
69
+ const NON_RETRIABLE_ERROR_NAMES = new Set([
70
+ 'ValidationError',
71
+ 'StateMachineError',
72
+ 'SchemaError',
73
+ 'AuthenticationError',
74
+ 'PermissionError',
75
+ 'BusinessLogicError',
76
+ 'InvalidStateTransition'
77
+ ]);
78
+
79
+ /**
80
+ * Non-retriable HTTP status codes (client errors)
81
+ */
82
+ const NON_RETRIABLE_STATUS_CODES = new Set([
83
+ 400, // Bad Request
84
+ 401, // Unauthorized
85
+ 403, // Forbidden
86
+ 404, // Not Found
87
+ 405, // Method Not Allowed
88
+ 406, // Not Acceptable
89
+ 409, // Conflict
90
+ 410, // Gone
91
+ 422 // Unprocessable Entity
92
+ ]);
93
+
94
+ export class ErrorClassifier {
95
+ /**
96
+ * Classify an error as RETRIABLE or NON_RETRIABLE
97
+ *
98
+ * @param {Error} error - The error to classify
99
+ * @param {Object} options - Classification options
100
+ * @param {Array<string>} options.retryableErrors - Custom retriable error names/codes
101
+ * @param {Array<string>} options.nonRetriableErrors - Custom non-retriable error names/codes
102
+ * @returns {string} 'RETRIABLE' or 'NON_RETRIABLE'
103
+ */
104
+ static classify(error, options = {}) {
105
+ if (!error) return NON_RETRIABLE;
106
+
107
+ const {
108
+ retryableErrors = [],
109
+ nonRetriableErrors = []
110
+ } = options;
111
+
112
+ // Check custom error lists first
113
+ if (retryableErrors.length > 0) {
114
+ const isCustomRetriable = retryableErrors.some(errType =>
115
+ error.code === errType ||
116
+ error.name === errType ||
117
+ error.message?.includes(errType)
118
+ );
119
+ if (isCustomRetriable) return RETRIABLE;
120
+ }
121
+
122
+ if (nonRetriableErrors.length > 0) {
123
+ const isCustomNonRetriable = nonRetriableErrors.some(errType =>
124
+ error.code === errType ||
125
+ error.name === errType ||
126
+ error.message?.includes(errType)
127
+ );
128
+ if (isCustomNonRetriable) return NON_RETRIABLE;
129
+ }
130
+
131
+ // Check explicit retriable property on error
132
+ if (error.retriable === false) return NON_RETRIABLE;
133
+ if (error.retriable === true) return RETRIABLE;
134
+
135
+ // Check for non-retriable error names
136
+ if (NON_RETRIABLE_ERROR_NAMES.has(error.name)) {
137
+ return NON_RETRIABLE;
138
+ }
139
+
140
+ // Check for non-retriable HTTP status codes
141
+ if (error.statusCode && NON_RETRIABLE_STATUS_CODES.has(error.statusCode)) {
142
+ return NON_RETRIABLE;
143
+ }
144
+
145
+ // Check for retriable network errors
146
+ if (error.code && RETRIABLE_NETWORK_CODES.has(error.code)) {
147
+ return RETRIABLE;
148
+ }
149
+
150
+ // Check for retriable AWS errors
151
+ if (error.code && RETRIABLE_AWS_CODES.has(error.code)) {
152
+ return RETRIABLE;
153
+ }
154
+
155
+ // Check for retriable AWS conflicts
156
+ if (error.code && RETRIABLE_AWS_CONFLICTS.has(error.code)) {
157
+ return RETRIABLE;
158
+ }
159
+
160
+ // Check for retriable HTTP status codes
161
+ if (error.statusCode && RETRIABLE_STATUS_CODES.has(error.statusCode)) {
162
+ return RETRIABLE;
163
+ }
164
+
165
+ // Check for timeout in error message
166
+ if (error.message && typeof error.message === 'string') {
167
+ const lowerMessage = error.message.toLowerCase();
168
+ if (lowerMessage.includes('timeout') ||
169
+ lowerMessage.includes('timed out') ||
170
+ lowerMessage.includes('network') ||
171
+ lowerMessage.includes('connection')) {
172
+ return RETRIABLE;
173
+ }
174
+ }
175
+
176
+ // Default: treat as retriable (conservative approach)
177
+ // This ensures transient failures are retried by default
178
+ return RETRIABLE;
179
+ }
180
+
181
+ /**
182
+ * Check if an error is retriable
183
+ *
184
+ * @param {Error} error - The error to check
185
+ * @param {Object} options - Classification options
186
+ * @returns {boolean} true if retriable
187
+ */
188
+ static isRetriable(error, options = {}) {
189
+ return this.classify(error, options) === RETRIABLE;
190
+ }
191
+
192
+ /**
193
+ * Check if an error is non-retriable
194
+ *
195
+ * @param {Error} error - The error to check
196
+ * @param {Object} options - Classification options
197
+ * @returns {boolean} true if non-retriable
198
+ */
199
+ static isNonRetriable(error, options = {}) {
200
+ return this.classify(error, options) === NON_RETRIABLE;
201
+ }
202
+ }
203
+
204
+ export { RETRIABLE, NON_RETRIABLE };
@@ -255,13 +255,13 @@ export class Database extends EventEmitter {
255
255
 
256
256
  // Emit definition changes if any were detected
257
257
  if (definitionChanges.length > 0) {
258
- this.emit("resourceDefinitionsChanged", {
258
+ this.emit("db:resource-definitions-changed", {
259
259
  changes: definitionChanges,
260
260
  metadata: this.savedMetadata
261
261
  });
262
262
  }
263
263
 
264
- this.emit("connected", new Date());
264
+ this.emit("db:connected", new Date());
265
265
  }
266
266
 
267
267
  /**
@@ -527,7 +527,7 @@ export class Database extends EventEmitter {
527
527
  this.pluginList.splice(index, 1);
528
528
  }
529
529
 
530
- this.emit('plugin.uninstalled', { name: pluginName, plugin });
530
+ this.emit('db:plugin:uninstalled', { name: pluginName, plugin });
531
531
  }
532
532
 
533
533
  async uploadMetadataFile() {
@@ -598,7 +598,7 @@ export class Database extends EventEmitter {
598
598
  });
599
599
 
600
600
  this.savedMetadata = metadata;
601
- this.emit('metadataUploaded', metadata);
601
+ this.emit('db:metadata-uploaded', metadata);
602
602
  }
603
603
 
604
604
  blankMetadataStructure() {
@@ -918,7 +918,7 @@ export class Database extends EventEmitter {
918
918
  contentType: 'application/json'
919
919
  });
920
920
 
921
- this.emit('metadataHealed', { healingLog, metadata });
921
+ this.emit('db:metadata-healed', { healingLog, metadata });
922
922
 
923
923
  if (this.verbose) {
924
924
  console.warn('S3DB: Successfully uploaded healed metadata');
@@ -1091,7 +1091,7 @@ export class Database extends EventEmitter {
1091
1091
  if (!existingVersionData || existingVersionData.hash !== newHash) {
1092
1092
  await this.uploadMetadataFile();
1093
1093
  }
1094
- this.emit("s3db.resourceUpdated", name);
1094
+ this.emit("db:resource:updated", name);
1095
1095
  return existingResource;
1096
1096
  }
1097
1097
  const existingMetadata = this.savedMetadata?.resources?.[name];
@@ -1131,7 +1131,7 @@ export class Database extends EventEmitter {
1131
1131
  }
1132
1132
 
1133
1133
  await this.uploadMetadataFile();
1134
- this.emit("s3db.resourceCreated", name);
1134
+ this.emit("db:resource:created", name);
1135
1135
  return resource;
1136
1136
  }
1137
1137
 
@@ -1290,7 +1290,7 @@ export class Database extends EventEmitter {
1290
1290
 
1291
1291
  // 4. Emit disconnected event BEFORE removing database listeners (race condition fix)
1292
1292
  // This ensures listeners can actually receive the event
1293
- await this.emit('disconnected', new Date());
1293
+ await this.emit('db:disconnected', new Date());
1294
1294
 
1295
1295
  // 5. Remove all listeners from the database itself
1296
1296
  this.removeAllListeners();
@@ -1427,7 +1427,7 @@ export class Database extends EventEmitter {
1427
1427
  const [ok, error] = await tryFn(() => hook({ database: this, ...context }));
1428
1428
  if (!ok) {
1429
1429
  // Emit error event
1430
- this.emit('hookError', { event, error, context });
1430
+ this.emit('db:hook-error', { event, error, context });
1431
1431
 
1432
1432
  // In strict mode, throw on first error instead of continuing
1433
1433
  if (this.strictHooks) {
@@ -149,7 +149,7 @@ export class BackupPlugin extends Plugin {
149
149
  console.log(`[BackupPlugin] Initialized with driver: ${storageInfo.type}`);
150
150
  }
151
151
 
152
- this.emit('initialized', {
152
+ this.emit('db:plugin:initialized', {
153
153
  driver: this.driver.getType(),
154
154
  config: this.driver.getStorageInfo()
155
155
  });
@@ -205,7 +205,7 @@ export class BackupPlugin extends Plugin {
205
205
  await this._executeHook(this.config.onBackupStart, type, { backupId });
206
206
  }
207
207
 
208
- this.emit('backup_start', { id: backupId, type });
208
+ this.emit('plg:backup:start', { id: backupId, type });
209
209
 
210
210
  // Create backup metadata
211
211
  const metadata = await this._createBackupMetadata(backupId, type);
@@ -262,7 +262,7 @@ export class BackupPlugin extends Plugin {
262
262
  await this._executeHook(this.config.onBackupComplete, type, stats);
263
263
  }
264
264
 
265
- this.emit('backup_complete', {
265
+ this.emit('plg:backup:complete', {
266
266
  id: backupId,
267
267
  type,
268
268
  size: totalSize,
@@ -300,7 +300,7 @@ export class BackupPlugin extends Plugin {
300
300
  duration: Date.now() - startTime
301
301
  });
302
302
 
303
- this.emit('backup_error', { id: backupId, type, error: error.message });
303
+ this.emit('plg:backup:error', { id: backupId, type, error: error.message });
304
304
  throw error;
305
305
 
306
306
  } finally {
@@ -579,7 +579,7 @@ export class BackupPlugin extends Plugin {
579
579
  await this._executeHook(this.config.onRestoreStart, backupId, options);
580
580
  }
581
581
 
582
- this.emit('restore_start', { id: backupId, options });
582
+ this.emit('plg:backup:restore-start', { id: backupId, options });
583
583
 
584
584
  // Get backup metadata
585
585
  const backup = await this.getBackupStatus(backupId);
@@ -616,7 +616,7 @@ export class BackupPlugin extends Plugin {
616
616
  await this._executeHook(this.config.onRestoreComplete, backupId, { restored: restoredResources });
617
617
  }
618
618
 
619
- this.emit('restore_complete', {
619
+ this.emit('plg:backup:restore-complete', {
620
620
  id: backupId,
621
621
  restored: restoredResources
622
622
  });
@@ -637,7 +637,7 @@ export class BackupPlugin extends Plugin {
637
637
  await this._executeHook(this.config.onRestoreError, backupId, { error });
638
638
  }
639
639
 
640
- this.emit('restore_error', { id: backupId, error: error.message });
640
+ this.emit('plg:backup:restore-error', { id: backupId, error: error.message });
641
641
  throw error;
642
642
  }
643
643
  }
@@ -973,7 +973,7 @@ export class BackupPlugin extends Plugin {
973
973
  async stop() {
974
974
  // Cancel any active backups
975
975
  for (const backupId of this.activeBackups) {
976
- this.emit('backup_cancelled', { id: backupId });
976
+ this.emit('plg:backup:cancelled', { id: backupId });
977
977
  }
978
978
  this.activeBackups.clear();
979
979
 
@@ -434,7 +434,7 @@ export class CachePlugin extends Plugin {
434
434
  const [ok, err] = await this.clearCacheWithRetry(resource.cache, specificKey);
435
435
 
436
436
  if (!ok) {
437
- this.emit('cache_clear_error', {
437
+ this.emit('plg:cache:clear-error', {
438
438
  resource: resource.name,
439
439
  method,
440
440
  id: data.id,
@@ -456,7 +456,7 @@ export class CachePlugin extends Plugin {
456
456
  const [ok, err] = await this.clearCacheWithRetry(resource.cache, partitionKeyPrefix);
457
457
 
458
458
  if (!ok) {
459
- this.emit('cache_clear_error', {
459
+ this.emit('plg:cache:clear-error', {
460
460
  resource: resource.name,
461
461
  partition: partitionName,
462
462
  error: err.message
@@ -475,7 +475,7 @@ export class CachePlugin extends Plugin {
475
475
  const [ok, err] = await this.clearCacheWithRetry(resource.cache, keyPrefix);
476
476
 
477
477
  if (!ok) {
478
- this.emit('cache_clear_error', {
478
+ this.emit('plg:cache:clear-error', {
479
479
  resource: resource.name,
480
480
  type: 'broad',
481
481
  error: err.message