s3db.js 9.1.0 → 9.2.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/PLUGINS.md CHANGED
@@ -18,6 +18,9 @@
18
18
  - [📊 Metrics Plugin](#-metrics-plugin)
19
19
  - [🔄 Replicator Plugin](#-replicator-plugin)
20
20
  - [📬 Queue Consumer Plugin](#-queue-consumer-plugin)
21
+ - [🤖 State Machine Plugin](#-state-machine-plugin)
22
+ - [💾 Backup Plugin](#-backup-plugin)
23
+ - [⏰ Scheduler Plugin](#-scheduler-plugin)
21
24
  - [🔧 Plugin Development](#-plugin-development)
22
25
  - [💡 Plugin Combinations](#-plugin-combinations)
23
26
  - [🎯 Best Practices](#-best-practices)
@@ -4143,6 +4146,501 @@ const s3db = new S3db({
4143
4146
 
4144
4147
  ---
4145
4148
 
4149
+ ## 🤖 State Machine Plugin
4150
+
4151
+ Finite state machine capabilities for managing complex workflows and business processes with well-defined states and transitions.
4152
+
4153
+ ### ⚡ Quick Start
4154
+
4155
+ ```javascript
4156
+ import { S3db, StateMachinePlugin } from 's3db.js';
4157
+
4158
+ const s3db = new S3db({
4159
+ connectionString: "s3://ACCESS_KEY:SECRET_KEY@BUCKET_NAME/databases/myapp",
4160
+ plugins: [
4161
+ new StateMachinePlugin({
4162
+ stateMachines: {
4163
+ order_processing: {
4164
+ initialState: 'pending',
4165
+ states: {
4166
+ pending: {
4167
+ on: { CONFIRM: 'confirmed', CANCEL: 'cancelled' }
4168
+ },
4169
+ confirmed: {
4170
+ on: { PREPARE: 'preparing', CANCEL: 'cancelled' },
4171
+ entry: 'onConfirmed'
4172
+ },
4173
+ preparing: {
4174
+ on: { SHIP: 'shipped', CANCEL: 'cancelled' },
4175
+ guards: { SHIP: 'canShip' }
4176
+ },
4177
+ shipped: {
4178
+ on: { DELIVER: 'delivered', RETURN: 'returned' }
4179
+ },
4180
+ delivered: { type: 'final' },
4181
+ cancelled: { type: 'final' },
4182
+ returned: { type: 'final' }
4183
+ }
4184
+ }
4185
+ },
4186
+ actions: {
4187
+ onConfirmed: async (context, event, machine) => {
4188
+ console.log(`Order ${context.id} confirmed!`);
4189
+ return { action: 'confirmed', timestamp: new Date() };
4190
+ }
4191
+ },
4192
+ guards: {
4193
+ canShip: async (context, event, machine) => {
4194
+ const inventory = await machine.database.resource('inventory').get(context.productId);
4195
+ return inventory && inventory.quantity >= context.quantity;
4196
+ }
4197
+ }
4198
+ })
4199
+ ]
4200
+ });
4201
+
4202
+ await s3db.connect();
4203
+
4204
+ // Initialize entity with state machine
4205
+ await s3db.plugins.stateMachine.initializeEntity('order_processing', 'order123');
4206
+
4207
+ // Send events to trigger transitions
4208
+ await s3db.plugins.stateMachine.send('order_processing', 'order123', 'CONFIRM', {
4209
+ id: 'order123',
4210
+ productId: 'prod1',
4211
+ quantity: 2
4212
+ });
4213
+
4214
+ // Get current state
4215
+ const state = await s3db.plugins.stateMachine.getState('order_processing', 'order123');
4216
+ console.log('Current state:', state); // 'confirmed'
4217
+ ```
4218
+
4219
+ ### ⚙️ Configuration Parameters
4220
+
4221
+ | Parameter | Type | Default | Description |
4222
+ |-----------|------|---------|-------------|
4223
+ | `stateMachines` | object | `{}` | State machine definitions |
4224
+ | `actions` | object | `{}` | Action functions for state entry/exit |
4225
+ | `guards` | object | `{}` | Guard functions for transition validation |
4226
+ | `persistTransitions` | boolean | `true` | Store transition history in database |
4227
+ | `transitionLogResource` | string | `'transitions'` | Resource name for transition log |
4228
+ | `stateResource` | string | `'entity_states'` | Resource name for current states |
4229
+ | `verbose` | boolean | `false` | Enable detailed logging |
4230
+
4231
+ ### State Machine Definition Structure
4232
+
4233
+ ```javascript
4234
+ stateMachines: {
4235
+ machine_name: {
4236
+ initialState: 'start_state',
4237
+ states: {
4238
+ state_name: {
4239
+ on: { EVENT_NAME: 'target_state' }, // Transitions
4240
+ entry: 'action_name', // Action on state entry
4241
+ exit: 'action_name', // Action on state exit
4242
+ guards: { EVENT_NAME: 'guard_name' }, // Transition guards
4243
+ meta: { custom: 'metadata' }, // Additional metadata
4244
+ type: 'final' // Mark as final state
4245
+ }
4246
+ }
4247
+ }
4248
+ }
4249
+ ```
4250
+
4251
+ ### API Methods
4252
+
4253
+ ```javascript
4254
+ // Entity management
4255
+ await stateMachine.initializeEntity(machineId, entityId, context);
4256
+ const state = await stateMachine.getState(machineId, entityId);
4257
+ const result = await stateMachine.send(machineId, entityId, event, context);
4258
+
4259
+ // State information
4260
+ const events = stateMachine.getValidEvents(machineId, entityId);
4261
+ const definition = stateMachine.getMachineDefinition(machineId);
4262
+ const machines = stateMachine.getMachines();
4263
+
4264
+ // History and visualization
4265
+ const history = await stateMachine.getTransitionHistory(machineId, entityId);
4266
+ const dot = stateMachine.visualize(machineId); // Graphviz DOT format
4267
+ ```
4268
+
4269
+ ### Events
4270
+
4271
+ ```javascript
4272
+ stateMachine.on('initialized', ({ machines }) => {
4273
+ console.log('Initialized machines:', machines);
4274
+ });
4275
+
4276
+ stateMachine.on('transition', ({ machineId, entityId, from, to, event, context }) => {
4277
+ console.log(`${entityId}: ${from} → ${to} via ${event}`);
4278
+ });
4279
+
4280
+ stateMachine.on('action_error', ({ actionName, error, machineId, entityId }) => {
4281
+ console.error(`Action ${actionName} failed:`, error);
4282
+ });
4283
+ ```
4284
+
4285
+ ---
4286
+
4287
+ ## 💾 Backup Plugin
4288
+
4289
+ Comprehensive database backup and restore capabilities with support for multiple destinations, compression, encryption, and retention policies.
4290
+
4291
+ ### ⚡ Quick Start
4292
+
4293
+ ```javascript
4294
+ import { S3db, BackupPlugin } from 's3db.js';
4295
+
4296
+ const s3db = new S3db({
4297
+ connectionString: "s3://ACCESS_KEY:SECRET_KEY@BUCKET_NAME/databases/myapp",
4298
+ plugins: [
4299
+ new BackupPlugin({
4300
+ destinations: [
4301
+ {
4302
+ type: 'filesystem',
4303
+ path: './backups/{date}/',
4304
+ compression: 'gzip'
4305
+ }
4306
+ ],
4307
+ retention: {
4308
+ daily: 7,
4309
+ weekly: 4,
4310
+ monthly: 12
4311
+ },
4312
+ onBackupComplete: (type, stats) => {
4313
+ console.log(`${type} backup completed:`, {
4314
+ size: `${Math.round(stats.size / 1024)}KB`,
4315
+ duration: `${stats.duration}ms`
4316
+ });
4317
+ }
4318
+ })
4319
+ ]
4320
+ });
4321
+
4322
+ await s3db.connect();
4323
+
4324
+ // Perform backups
4325
+ const fullBackup = await s3db.plugins.backup.backup('full');
4326
+ console.log('Backup ID:', fullBackup.id);
4327
+
4328
+ const incrementalBackup = await s3db.plugins.backup.backup('incremental');
4329
+
4330
+ // List available backups
4331
+ const backups = await s3db.plugins.backup.listBackups();
4332
+ console.log('Available backups:', backups.length);
4333
+
4334
+ // Restore from backup
4335
+ // await s3db.plugins.backup.restore(fullBackup.id);
4336
+ ```
4337
+
4338
+ ### ⚙️ Configuration Parameters
4339
+
4340
+ | Parameter | Type | Default | Description |
4341
+ |-----------|------|---------|-------------|
4342
+ | `destinations` | array | `[]` | Backup destinations configuration |
4343
+ | `retention` | object | `{}` | Retention policy (daily, weekly, monthly, yearly) |
4344
+ | `include` | array | `null` | Resources to include (null = all) |
4345
+ | `exclude` | array | `[]` | Resources to exclude (supports wildcards) |
4346
+ | `compression` | string | `'gzip'` | Compression: `'none'`, `'gzip'`, `'brotli'` |
4347
+ | `encryption` | object | `null` | Encryption configuration |
4348
+ | `verification` | boolean | `true` | Verify backup integrity |
4349
+ | `tempDir` | string | `'./tmp/backups'` | Temporary working directory |
4350
+ | `onBackupStart` | function | `null` | Callback when backup starts |
4351
+ | `onBackupComplete` | function | `null` | Callback when backup completes |
4352
+ | `onBackupError` | function | `null` | Callback when backup fails |
4353
+ | `verbose` | boolean | `false` | Enable detailed logging |
4354
+
4355
+ ### Destination Types
4356
+
4357
+ #### Filesystem
4358
+ ```javascript
4359
+ {
4360
+ type: 'filesystem',
4361
+ path: '/backups/{date}/', // {date} expands to YYYY-MM-DD
4362
+ compression: 'gzip'
4363
+ }
4364
+ ```
4365
+
4366
+ #### Amazon S3
4367
+ ```javascript
4368
+ {
4369
+ type: 's3',
4370
+ bucket: 'backup-bucket',
4371
+ path: 'db-backups/{date}/',
4372
+ region: 'us-east-1',
4373
+ storageClass: 'STANDARD_IA'
4374
+ }
4375
+ ```
4376
+
4377
+ ### Backup Types
4378
+
4379
+ ```javascript
4380
+ // Full backup - complete snapshot
4381
+ const fullBackup = await backup.backup('full');
4382
+
4383
+ // Incremental backup - changes since last backup
4384
+ const incrementalBackup = await backup.backup('incremental');
4385
+
4386
+ // Differential backup - changes since last full backup
4387
+ const differentialBackup = await backup.backup('differential');
4388
+ ```
4389
+
4390
+ ### Retention Policies (GFS)
4391
+
4392
+ ```javascript
4393
+ retention: {
4394
+ daily: 7, // Keep daily backups for 7 days
4395
+ weekly: 4, // Keep weekly backups for 4 weeks
4396
+ monthly: 12, // Keep monthly backups for 12 months
4397
+ yearly: 3 // Keep yearly backups for 3 years
4398
+ }
4399
+ ```
4400
+
4401
+ ### API Methods
4402
+
4403
+ ```javascript
4404
+ // Backup operations
4405
+ const result = await backup.backup(type, options);
4406
+ const backups = await backup.listBackups({ type: 'full', limit: 10 });
4407
+ const status = await backup.getBackupStatus(backupId);
4408
+ await backup.restore(backupId, options);
4409
+
4410
+ // Management
4411
+ await backup.cleanup(); // Apply retention policy
4412
+ const isValid = await backup.verify(backupId);
4413
+ await backup.cancel(backupId);
4414
+ ```
4415
+
4416
+ ### Events
4417
+
4418
+ ```javascript
4419
+ backup.on('backup_start', ({ id, type }) => {
4420
+ console.log(`Backup ${id} started (${type})`);
4421
+ });
4422
+
4423
+ backup.on('backup_complete', ({ id, type, size, duration, destinations }) => {
4424
+ console.log(`Backup ${id} completed in ${duration}ms`);
4425
+ });
4426
+
4427
+ backup.on('backup_error', ({ id, type, error }) => {
4428
+ console.error(`Backup ${id} failed:`, error);
4429
+ });
4430
+ ```
4431
+
4432
+ ---
4433
+
4434
+ ## ⏰ Scheduler Plugin
4435
+
4436
+ Robust job scheduling capabilities with cron expressions, retry logic, and comprehensive monitoring for automated tasks.
4437
+
4438
+ ### ⚡ Quick Start
4439
+
4440
+ ```javascript
4441
+ import { S3db, SchedulerPlugin } from 's3db.js';
4442
+
4443
+ const s3db = new S3db({
4444
+ connectionString: "s3://ACCESS_KEY:SECRET_KEY@BUCKET_NAME/databases/myapp",
4445
+ plugins: [
4446
+ new SchedulerPlugin({
4447
+ timezone: 'America/Sao_Paulo',
4448
+ jobs: {
4449
+ daily_cleanup: {
4450
+ schedule: '0 3 * * *', // 3 AM daily
4451
+ description: 'Clean up expired sessions',
4452
+ action: async (database, context) => {
4453
+ const expired = await database.resource('sessions').list({
4454
+ where: { expiresAt: { $lt: new Date() } }
4455
+ });
4456
+
4457
+ for (const session of expired) {
4458
+ await database.resource('sessions').delete(session.id);
4459
+ }
4460
+
4461
+ return { deleted: expired.length };
4462
+ },
4463
+ enabled: true,
4464
+ retries: 2,
4465
+ timeout: 30000
4466
+ },
4467
+
4468
+ hourly_metrics: {
4469
+ schedule: '@hourly',
4470
+ description: 'Collect system metrics',
4471
+ action: async (database) => {
4472
+ const metrics = {
4473
+ timestamp: new Date().toISOString(),
4474
+ memory: process.memoryUsage(),
4475
+ uptime: process.uptime()
4476
+ };
4477
+
4478
+ await database.resource('metrics').insert({
4479
+ id: `metrics_${Date.now()}`,
4480
+ ...metrics
4481
+ });
4482
+
4483
+ return metrics;
4484
+ }
4485
+ }
4486
+ },
4487
+ onJobComplete: (jobName, result, duration) => {
4488
+ console.log(`Job ${jobName} completed in ${duration}ms`);
4489
+ }
4490
+ })
4491
+ ]
4492
+ });
4493
+
4494
+ await s3db.connect();
4495
+
4496
+ // Jobs run automatically based on schedule
4497
+ // Manual execution
4498
+ await s3db.plugins.scheduler.runJob('daily_cleanup');
4499
+
4500
+ // Get job status
4501
+ const allJobs = s3db.plugins.scheduler.getAllJobsStatus();
4502
+ console.log('Scheduled jobs:', allJobs.length);
4503
+ ```
4504
+
4505
+ ### ⚙️ Configuration Parameters
4506
+
4507
+ | Parameter | Type | Default | Description |
4508
+ |-----------|------|---------|-------------|
4509
+ | `timezone` | string | `'UTC'` | IANA timezone identifier |
4510
+ | `jobs` | object | `{}` | Job definitions |
4511
+ | `defaultTimeout` | number | `60000` | Default job timeout (ms) |
4512
+ | `defaultRetries` | number | `1` | Default retry attempts |
4513
+ | `persistJobs` | boolean | `true` | Store job execution history |
4514
+ | `jobHistoryResource` | string | `'job_history'` | Resource for job history |
4515
+ | `onJobStart` | function | `null` | Callback when job starts |
4516
+ | `onJobComplete` | function | `null` | Callback when job completes |
4517
+ | `onJobError` | function | `null` | Callback when job fails |
4518
+ | `verbose` | boolean | `false` | Enable detailed logging |
4519
+
4520
+ ### Job Configuration
4521
+
4522
+ ```javascript
4523
+ jobs: {
4524
+ job_name: {
4525
+ schedule: '0 0 * * *', // Cron expression (required)
4526
+ description: 'Job description', // Human-readable description
4527
+ action: async (database, context, schedulerPlugin) => {
4528
+ // Job implementation (required)
4529
+ return { success: true };
4530
+ },
4531
+ enabled: true, // Enable/disable job
4532
+ retries: 2, // Retry attempts on failure
4533
+ timeout: 30000, // Timeout in milliseconds
4534
+ meta: { priority: 'high' } // Custom metadata
4535
+ }
4536
+ }
4537
+ ```
4538
+
4539
+ ### Cron Expressions
4540
+
4541
+ #### Standard Format
4542
+ ```
4543
+ * * * * *
4544
+ │ │ │ │ │
4545
+ │ │ │ │ └─── Day of week (0-7, Sunday = 0 or 7)
4546
+ │ │ │ └───── Month (1-12)
4547
+ │ │ └─────── Day of month (1-31)
4548
+ │ └───────── Hour (0-23)
4549
+ └─────────── Minute (0-59)
4550
+ ```
4551
+
4552
+ #### Examples
4553
+ ```javascript
4554
+ '0 0 * * *' // Daily at midnight
4555
+ '0 9 * * MON' // Every Monday at 9 AM
4556
+ '*/15 * * * *' // Every 15 minutes
4557
+ '0 2 1 * *' // First day of month at 2 AM
4558
+ ```
4559
+
4560
+ #### Shorthand Expressions
4561
+ ```javascript
4562
+ '@yearly' // Once a year at midnight on January 1st
4563
+ '@monthly' // Once a month at midnight on the 1st
4564
+ '@weekly' // Once a week at midnight on Sunday
4565
+ '@daily' // Once a day at midnight
4566
+ '@hourly' // Once an hour at the beginning of the hour
4567
+ ```
4568
+
4569
+ ### API Methods
4570
+
4571
+ ```javascript
4572
+ // Job execution
4573
+ const result = await scheduler.runJob(jobName, context);
4574
+ const stats = scheduler.getJobStatus(jobName);
4575
+ const allJobs = scheduler.getAllJobsStatus();
4576
+
4577
+ // Job management
4578
+ scheduler.enableJob(jobName);
4579
+ scheduler.disableJob(jobName);
4580
+ scheduler.addJob(jobName, jobConfig);
4581
+ scheduler.removeJob(jobName);
4582
+
4583
+ // History and monitoring
4584
+ const history = await scheduler.getJobHistory(jobName, { status: 'success', limit: 10 });
4585
+ const stats = scheduler.getJobStatistics(jobName);
4586
+ ```
4587
+
4588
+ ### Events
4589
+
4590
+ ```javascript
4591
+ scheduler.on('job_start', ({ jobName, context }) => {
4592
+ console.log(`Job ${jobName} started`);
4593
+ });
4594
+
4595
+ scheduler.on('job_complete', ({ jobName, result, duration }) => {
4596
+ console.log(`Job ${jobName} completed in ${duration}ms`);
4597
+ });
4598
+
4599
+ scheduler.on('job_error', ({ jobName, error, retryCount }) => {
4600
+ console.error(`Job ${jobName} failed (attempt ${retryCount}):`, error);
4601
+ });
4602
+
4603
+ scheduler.on('job_enabled', ({ jobName }) => {
4604
+ console.log(`Job ${jobName} enabled`);
4605
+ });
4606
+ ```
4607
+
4608
+ ### Integration with Other Plugins
4609
+
4610
+ ```javascript
4611
+ // Scheduled backups
4612
+ jobs: {
4613
+ daily_backup: {
4614
+ schedule: '0 1 * * *',
4615
+ action: async (database) => {
4616
+ const backup = database.getPlugin('BackupPlugin');
4617
+ return await backup.backup('full');
4618
+ }
4619
+ }
4620
+ }
4621
+
4622
+ // Process state machine entities
4623
+ jobs: {
4624
+ process_pending_orders: {
4625
+ schedule: '*/10 * * * *',
4626
+ action: async (database) => {
4627
+ const stateMachine = database.getPlugin('StateMachinePlugin');
4628
+ const orders = await database.resource('orders').list({
4629
+ where: { status: 'pending' }
4630
+ });
4631
+
4632
+ for (const order of orders) {
4633
+ await stateMachine.send('order_processing', order.id, 'AUTO_PROCESS');
4634
+ }
4635
+
4636
+ return { processed: orders.length };
4637
+ }
4638
+ }
4639
+ }
4640
+ ```
4641
+
4642
+ ---
4643
+
4146
4644
  ## 🎯 Best Practices
4147
4645
 
4148
4646
  ### Plugin Performance
@@ -4152,6 +4650,9 @@ const s3db = new S3db({
4152
4650
  3. **Use appropriate sampling** for metrics collection
4153
4651
  4. **Configure retention policies** for audit logs
4154
4652
  5. **Test replicator connections** before deployment
4653
+ 6. **Design efficient state machines** with minimal guards and actions
4654
+ 7. **Schedule backups during low-traffic periods** to minimize impact
4655
+ 8. **Use appropriate job timeouts** to prevent resource exhaustion
4155
4656
 
4156
4657
  ### Plugin Security
4157
4658
 
@@ -4160,6 +4661,9 @@ const s3db = new S3db({
4160
4661
  3. **Use IAM roles** instead of access keys when possible
4161
4662
  4. **Encrypt replication data** in transit and at rest
4162
4663
  5. **Validate message sources** in queue consumers
4664
+ 6. **Secure state machine actions** to prevent unauthorized transitions
4665
+ 7. **Encrypt backup data** for sensitive databases
4666
+ 8. **Restrict job execution permissions** to necessary resources only
4163
4667
 
4164
4668
  ### Plugin Monitoring
4165
4669
 
@@ -4168,6 +4672,9 @@ const s3db = new S3db({
4168
4672
  3. **Track error rates** across all plugins
4169
4673
  4. **Use structured logging** for debugging
4170
4674
  5. **Implement circuit breakers** for external services
4675
+ 6. **Monitor state machine transition rates** and error patterns
4676
+ 7. **Track backup success rates** and storage usage
4677
+ 8. **Alert on job failures** and execution delays
4171
4678
 
4172
4679
  ---
4173
4680