s3db.js 13.2.2 → 13.3.0

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.2.2",
3
+ "version": "13.3.0",
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",
@@ -74,6 +74,7 @@ export class MemoryClient extends EventEmitter {
74
74
  const input = command.input || {};
75
75
 
76
76
  this.emit('cl:request', commandName, input);
77
+ this.emit('command.request', commandName, input);
77
78
 
78
79
  let response;
79
80
 
@@ -106,6 +107,7 @@ export class MemoryClient extends EventEmitter {
106
107
  }
107
108
 
108
109
  this.emit('cl:response', commandName, response, input);
110
+ this.emit('command.response', commandName, response, input);
109
111
  return response;
110
112
 
111
113
  } catch (error) {
@@ -479,14 +481,14 @@ export class MemoryClient extends EventEmitter {
479
481
  const result = await this.deleteObjects(keys);
480
482
  totalDeleted = result.Deleted.length;
481
483
 
482
- this.emit('cl:DeleteAll', {
484
+ this.emit('deleteAll', {
483
485
  prefix,
484
486
  batch: totalDeleted,
485
487
  total: totalDeleted
486
488
  });
487
489
  }
488
490
 
489
- this.emit('cl:DeleteAllComplete', {
491
+ this.emit('deleteAllComplete', {
490
492
  prefix,
491
493
  totalDeleted
492
494
  });
@@ -544,7 +546,7 @@ export class MemoryClient extends EventEmitter {
544
546
  }
545
547
  }
546
548
 
547
- this.emit('cl:MoveAllObjects', { results, errors }, { prefixFrom, prefixTo });
549
+ this.emit('moveAllObjects', { results, errors });
548
550
 
549
551
  if (errors.length > 0) {
550
552
  const error = new Error('Some objects could not be moved');
@@ -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("db:resource:updated", name);
1094
+ this.emit("s3db.resourceUpdated", 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("db:resource:created", name);
1134
+ this.emit("s3db.resourceCreated", name);
1135
1135
  return resource;
1136
1136
  }
1137
1137
 
@@ -1239,6 +1239,9 @@ export class Database extends EventEmitter {
1239
1239
  }
1240
1240
 
1241
1241
  async disconnect() {
1242
+ // Emit disconnected event BEFORE removing listeners (Fix #2)
1243
+ await this.emit('disconnected', new Date());
1244
+
1242
1245
  // Silently ignore all errors during disconnect
1243
1246
  await tryFn(async () => {
1244
1247
  // 1. Remove all listeners from all plugins
@@ -1427,7 +1430,7 @@ export class Database extends EventEmitter {
1427
1430
  const [ok, error] = await tryFn(() => hook({ database: this, ...context }));
1428
1431
  if (!ok) {
1429
1432
  // Emit error event
1430
- this.emit('db:hook-error', { event, error, context });
1433
+ this.emit('hookError', { event, error, context });
1431
1434
 
1432
1435
  // In strict mode, throw on first error instead of continuing
1433
1436
  if (this.strictHooks) {
@@ -65,7 +65,7 @@ export class AuditPlugin extends Plugin {
65
65
 
66
66
  setupResourceAuditing(resource) {
67
67
  // Insert
68
- resource.on('insert', async (data) => {
68
+ resource.on('inserted', async (data) => {
69
69
  const partitionValues = this.config.includePartitions ? this.getPartitionValues(data, resource) : null;
70
70
  await this.logAudit({
71
71
  resourceName: resource.name,
@@ -79,7 +79,7 @@ export class AuditPlugin extends Plugin {
79
79
  });
80
80
 
81
81
  // Update
82
- resource.on('update', async (data) => {
82
+ resource.on('updated', async (data) => {
83
83
  let oldData = data.$before;
84
84
  if (this.config.includeData && !oldData) {
85
85
  const [ok, err, fetched] = await tryFn(() => resource.get(data.id));
@@ -99,7 +99,7 @@ export class AuditPlugin extends Plugin {
99
99
  });
100
100
 
101
101
  // Delete
102
- resource.on('delete', async (data) => {
102
+ resource.on('deleted', async (data) => {
103
103
  let oldData = data;
104
104
  if (this.config.includeData && !oldData) {
105
105
  const [ok, err, fetched] = await tryFn(() => resource.get(data.id));
@@ -35,14 +35,14 @@ export class Cache extends EventEmitter {
35
35
  async get(key) {
36
36
  this.validateKey(key);
37
37
  const data = await this._get(key);
38
- this.emit("get", data);
38
+ this.emit("fetched", data);
39
39
  return data;
40
40
  }
41
41
 
42
42
  async del(key) {
43
43
  this.validateKey(key);
44
44
  const data = await this._del(key);
45
- this.emit("delete", data);
45
+ this.emit("deleted", data);
46
46
  return data;
47
47
  }
48
48
 
@@ -110,8 +110,9 @@ export class CostsPlugin extends Plugin {
110
110
 
111
111
  async onStart() {
112
112
  if (this.client) {
113
- this.client.on("command.response", (name, response, input) => this.addRequest(name, this.map[name], response, input));
114
- this.client.on("command.error", (name, response, input) => this.addRequest(name, this.map[name], response, input));
113
+ // Listen to cl:response only (fires for all operations, success or error)
114
+ // This prevents double-counting (cl:request + cl:response would count twice)
115
+ this.client.on("cl:response", (name, response, input) => this.addRequest(name, this.map[name], response, input));
115
116
  }
116
117
  }
117
118
 
@@ -252,15 +252,15 @@ export class ReplicatorPlugin extends Plugin {
252
252
 
253
253
  // Save handler references
254
254
  this.eventHandlers.set(resource.name, {
255
- insert: insertHandler,
256
- update: updateHandler,
257
- delete: deleteHandler
255
+ inserted: insertHandler,
256
+ updated: updateHandler,
257
+ deleted: deleteHandler
258
258
  });
259
259
 
260
- // Attach listeners
261
- resource.on('insert', insertHandler);
262
- resource.on('update', updateHandler);
263
- resource.on('delete', deleteHandler);
260
+ // Attach listeners (use standardized past tense event names)
261
+ resource.on('inserted', insertHandler);
262
+ resource.on('updated', updateHandler);
263
+ resource.on('deleted', deleteHandler);
264
264
 
265
265
  this.eventListenersInstalled.add(resource.name);
266
266
  }
@@ -753,9 +753,9 @@ export class ReplicatorPlugin extends Plugin {
753
753
  const handlers = this.eventHandlers.get(resourceName);
754
754
 
755
755
  if (resource && handlers) {
756
- resource.off('insert', handlers.insert);
757
- resource.off('update', handlers.update);
758
- resource.off('delete', handlers.delete);
756
+ resource.off('inserted', handlers.inserted);
757
+ resource.off('updated', handlers.updated);
758
+ resource.off('deleted', handlers.deleted);
759
759
  }
760
760
  }
761
761
  }
@@ -20,7 +20,7 @@ export class BaseReplicator extends EventEmitter {
20
20
  */
21
21
  async initialize(database) {
22
22
  this.database = database;
23
- this.emit('initialized', { replicator: this.name });
23
+ this.emit('db:plugin:initialized', { replicator: this.name });
24
24
  }
25
25
 
26
26
  /**
@@ -189,7 +189,7 @@ class BigqueryReplicator extends BaseReplicator {
189
189
  await this.syncSchemas(database);
190
190
  }
191
191
 
192
- this.emit('initialized', {
192
+ this.emit('db:plugin:initialized', {
193
193
  replicator: this.name,
194
194
  projectId: this.projectId,
195
195
  datasetId: this.datasetId,
@@ -598,7 +598,7 @@ class BigqueryReplicator extends BaseReplicator {
598
598
  console.warn(`[BigqueryReplicator] Replication completed with errors for ${resourceName}:`, errors);
599
599
  }
600
600
 
601
- this.emit('replicated', {
601
+ this.emit('plg:replicator:replicated', {
602
602
  replicator: this.name,
603
603
  resourceName,
604
604
  operation,
@@ -622,7 +622,7 @@ class BigqueryReplicator extends BaseReplicator {
622
622
  if (this.config.verbose) {
623
623
  console.warn(`[BigqueryReplicator] Replication failed for ${resourceName}: ${err.message}`);
624
624
  }
625
- this.emit('replicator_error', {
625
+ this.emit('plg:replicator:error', {
626
626
  replicator: this.name,
627
627
  resourceName,
628
628
  operation,
@@ -369,7 +369,7 @@ class PlanetScaleReplicator extends BaseReplicator {
369
369
 
370
370
  const success = errors.length === 0;
371
371
 
372
- this.emit('replicated', {
372
+ this.emit('plg:replicator:replicated', {
373
373
  replicator: this.name,
374
374
  resourceName,
375
375
  operation,
@@ -180,7 +180,7 @@ class PostgresReplicator extends BaseReplicator {
180
180
  await this.syncSchemas(database);
181
181
  }
182
182
 
183
- this.emit('initialized', {
183
+ this.emit('db:plugin:initialized', {
184
184
  replicator: this.name,
185
185
  database: this.database || 'postgres',
186
186
  resources: Object.keys(this.resources)
@@ -452,7 +452,7 @@ class PostgresReplicator extends BaseReplicator {
452
452
  console.warn(`[PostgresReplicator] Replication completed with errors for ${resourceName}:`, errors);
453
453
  }
454
454
 
455
- this.emit('replicated', {
455
+ this.emit('plg:replicator:replicated', {
456
456
  replicator: this.name,
457
457
  resourceName,
458
458
  operation,
@@ -473,7 +473,7 @@ class PostgresReplicator extends BaseReplicator {
473
473
  if (this.config.verbose) {
474
474
  console.warn(`[PostgresReplicator] Replication failed for ${resourceName}: ${err.message}`);
475
475
  }
476
- this.emit('replicator_error', {
476
+ this.emit('plg:replicator:error', {
477
477
  replicator: this.name,
478
478
  resourceName,
479
479
  operation,
@@ -182,7 +182,7 @@ class SqsReplicator extends BaseReplicator {
182
182
  region: this.region,
183
183
  credentials: this.config.credentials
184
184
  });
185
- this.emit('initialized', {
185
+ this.emit('db:plugin:initialized', {
186
186
  replicator: this.name,
187
187
  queueUrl: this.queueUrl,
188
188
  queues: this.queues,
@@ -214,7 +214,7 @@ class SqsReplicator extends BaseReplicator {
214
214
  });
215
215
  const result = await this.sqsClient.send(command);
216
216
  results.push({ queueUrl, messageId: result.MessageId });
217
- this.emit('replicated', {
217
+ this.emit('plg:replicator:replicated', {
218
218
  replicator: this.name,
219
219
  resource,
220
220
  operation,
@@ -230,7 +230,7 @@ class SqsReplicator extends BaseReplicator {
230
230
  if (this.config.verbose) {
231
231
  console.warn(`[SqsReplicator] Replication failed for ${resource}: ${err.message}`);
232
232
  }
233
- this.emit('replicator_error', {
233
+ this.emit('plg:replicator:error', {
234
234
  replicator: this.name,
235
235
  resource,
236
236
  operation,
@@ -374,7 +374,7 @@ class TursoReplicator extends BaseReplicator {
374
374
 
375
375
  const success = errors.length === 0;
376
376
 
377
- this.emit('replicated', {
377
+ this.emit('plg:replicator:replicated', {
378
378
  replicator: this.name,
379
379
  resourceName,
380
380
  operation,
@@ -399,7 +399,7 @@ class WebhookReplicator extends BaseReplicator {
399
399
  throw error;
400
400
  }
401
401
 
402
- this.emit('initialized', {
402
+ this.emit('db:plugin:initialized', {
403
403
  replicator: this.name,
404
404
  url: this.url,
405
405
  method: this.method,
@@ -428,7 +428,7 @@ class WebhookReplicator extends BaseReplicator {
428
428
  const response = await this._makeRequest(payload);
429
429
 
430
430
  if (response.success) {
431
- this.emit('replicated', {
431
+ this.emit('plg:replicator:replicated', {
432
432
  replicator: this.name,
433
433
  resource,
434
434
  operation,
@@ -450,7 +450,7 @@ class WebhookReplicator extends BaseReplicator {
450
450
  console.warn(`[WebhookReplicator] Replication failed for ${resource}: ${err.message}`);
451
451
  }
452
452
 
453
- this.emit('replicator_error', {
453
+ this.emit('plg:replicator:error', {
454
454
  replicator: this.name,
455
455
  resource,
456
456
  operation,
@@ -195,7 +195,7 @@ export class S3QueuePlugin extends Plugin {
195
195
 
196
196
  await plugin.queueResource.insert(queueEntry);
197
197
 
198
- plugin.emit('message.enqueued', { id: record.id, queueId: queueEntry.id });
198
+ plugin.emit('plg:s3-queue:message-enqueued', { id: record.id, queueId: queueEntry.id });
199
199
 
200
200
  return record;
201
201
  };