s3db.js 13.3.0 → 13.4.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/README.md +34 -10
- package/dist/s3db.cjs.js +102 -23
- package/dist/s3db.cjs.js.map +1 -1
- package/dist/s3db.es.js +102 -23
- package/dist/s3db.es.js.map +1 -1
- package/package.json +15 -2
- package/src/plugins/audit.plugin.js +427 -0
- package/src/plugins/costs.plugin.js +524 -0
- package/src/plugins/fulltext.plugin.js +484 -0
- package/src/plugins/metrics.plugin.js +575 -0
- package/src/plugins/queue-consumer.plugin.js +607 -19
- package/src/plugins/state-machine.plugin.js +132 -26
|
@@ -1,3 +1,527 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # CostsPlugin - AWS S3 Cost Tracking for s3db.js
|
|
3
|
+
*
|
|
4
|
+
* ## Overview
|
|
5
|
+
*
|
|
6
|
+
* The CostsPlugin automatically tracks AWS S3 costs in real-time, providing detailed
|
|
7
|
+
* cost breakdowns for requests, storage, and data transfer. Perfect for monitoring
|
|
8
|
+
* and optimizing S3 usage costs.
|
|
9
|
+
*
|
|
10
|
+
* ## Features
|
|
11
|
+
*
|
|
12
|
+
* 1. **Real-Time Cost Tracking** - Monitor costs as operations occur
|
|
13
|
+
* 2. **Tiered Pricing** - Accurate AWS S3 tiered pricing calculations
|
|
14
|
+
* 3. **Request Tracking** - Track PUT, GET, COPY, HEAD, DELETE, LIST operations
|
|
15
|
+
* 4. **Storage Costs** - Calculate monthly storage costs with tiered pricing
|
|
16
|
+
* 5. **Data Transfer Costs** - Track upload (free) and download (tiered) costs
|
|
17
|
+
* 6. **Free Tier Support** - Optional AWS free tier consideration
|
|
18
|
+
* 7. **Detailed Breakdown** - Access costs by operation type, resource, and category
|
|
19
|
+
*
|
|
20
|
+
* ## Configuration
|
|
21
|
+
*
|
|
22
|
+
* ```javascript
|
|
23
|
+
* import { Database } from 's3db.js';
|
|
24
|
+
* import { CostsPlugin } from 's3db.js/plugins/costs';
|
|
25
|
+
*
|
|
26
|
+
* // Basic configuration
|
|
27
|
+
* const db = new Database({
|
|
28
|
+
* connectionString: 's3://bucket/db'
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* await db.use(new CostsPlugin({
|
|
32
|
+
* considerFreeTier: false, // Don't apply free tier (default: false)
|
|
33
|
+
* region: 'us-east-1' // AWS region (default: 'us-east-1')
|
|
34
|
+
* }));
|
|
35
|
+
*
|
|
36
|
+
* // With free tier consideration
|
|
37
|
+
* await db.use(new CostsPlugin({
|
|
38
|
+
* considerFreeTier: true, // Apply AWS free tier (100GB data transfer)
|
|
39
|
+
* region: 'us-east-1'
|
|
40
|
+
* }));
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* ## Usage Examples
|
|
44
|
+
*
|
|
45
|
+
* ### Basic Cost Tracking
|
|
46
|
+
*
|
|
47
|
+
* ```javascript
|
|
48
|
+
* const db = new Database({ connectionString: 's3://bucket/db' });
|
|
49
|
+
* await db.use(new CostsPlugin());
|
|
50
|
+
* await db.start();
|
|
51
|
+
*
|
|
52
|
+
* const users = await db.createResource({
|
|
53
|
+
* name: 'users',
|
|
54
|
+
* attributes: { name: 'string', email: 'string' }
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* // Perform operations
|
|
58
|
+
* await users.insert({ id: 'u1', name: 'John', email: 'john@example.com' });
|
|
59
|
+
* await users.get('u1');
|
|
60
|
+
* await users.update('u1', { name: 'Jane' });
|
|
61
|
+
*
|
|
62
|
+
* // Access costs from client
|
|
63
|
+
* console.log(db.client.costs);
|
|
64
|
+
* // {
|
|
65
|
+
* // total: 0.0000154,
|
|
66
|
+
* // requests: {
|
|
67
|
+
* // total: 3,
|
|
68
|
+
* // counts: { put: 2, get: 1 },
|
|
69
|
+
* // subtotal: 0.0000134
|
|
70
|
+
* // },
|
|
71
|
+
* // storage: { totalGB: 0.00001, subtotal: 0.00000023 },
|
|
72
|
+
* // dataTransfer: { inGB: 0.00001, outGB: 0.00001, subtotal: 0.0 }
|
|
73
|
+
* // }
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* ### Detailed Cost Breakdown
|
|
77
|
+
*
|
|
78
|
+
* ```javascript
|
|
79
|
+
* const costs = db.client.costs;
|
|
80
|
+
*
|
|
81
|
+
* // Total costs
|
|
82
|
+
* console.log(`Total: $${costs.total.toFixed(6)}`);
|
|
83
|
+
*
|
|
84
|
+
* // Request costs
|
|
85
|
+
* console.log('Requests:', {
|
|
86
|
+
* put: costs.requests.counts.put,
|
|
87
|
+
* get: costs.requests.counts.get,
|
|
88
|
+
* copy: costs.requests.counts.copy,
|
|
89
|
+
* list: costs.requests.counts.list,
|
|
90
|
+
* delete: costs.requests.counts.delete,
|
|
91
|
+
* head: costs.requests.counts.head,
|
|
92
|
+
* subtotal: `$${costs.requests.subtotal.toFixed(6)}`
|
|
93
|
+
* });
|
|
94
|
+
*
|
|
95
|
+
* // Storage costs
|
|
96
|
+
* console.log('Storage:', {
|
|
97
|
+
* totalGB: costs.storage.totalGB.toFixed(4),
|
|
98
|
+
* currentTier: costs.storage.currentTier,
|
|
99
|
+
* subtotal: `$${costs.storage.subtotal.toFixed(6)}`
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* // Data transfer costs
|
|
103
|
+
* console.log('Data Transfer:', {
|
|
104
|
+
* inGB: costs.dataTransfer.inGB.toFixed(4),
|
|
105
|
+
* outGB: costs.dataTransfer.outGB.toFixed(4),
|
|
106
|
+
* freeTierUsed: costs.dataTransfer.freeTierUsed.toFixed(4),
|
|
107
|
+
* subtotal: `$${costs.dataTransfer.subtotal.toFixed(6)}`
|
|
108
|
+
* });
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* ### Cost Monitoring Dashboard
|
|
112
|
+
*
|
|
113
|
+
* ```javascript
|
|
114
|
+
* // Real-time cost monitoring
|
|
115
|
+
* setInterval(() => {
|
|
116
|
+
* const costs = db.client.costs;
|
|
117
|
+
* const report = {
|
|
118
|
+
* timestamp: new Date().toISOString(),
|
|
119
|
+
* total: `$${costs.total.toFixed(6)}`,
|
|
120
|
+
* operations: costs.requests.total,
|
|
121
|
+
* storage: `${costs.storage.totalGB.toFixed(2)} GB`,
|
|
122
|
+
* dataTransfer: {
|
|
123
|
+
* in: `${costs.dataTransfer.inGB.toFixed(2)} GB`,
|
|
124
|
+
* out: `${costs.dataTransfer.outGB.toFixed(2)} GB`
|
|
125
|
+
* }
|
|
126
|
+
* };
|
|
127
|
+
*
|
|
128
|
+
* console.log('Cost Report:', report);
|
|
129
|
+
* // Send to monitoring system
|
|
130
|
+
* sendToMonitoring(report);
|
|
131
|
+
* }, 60000); // Every minute
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* ### Cost Alerts
|
|
135
|
+
*
|
|
136
|
+
* ```javascript
|
|
137
|
+
* // Set up cost threshold alerts
|
|
138
|
+
* const COST_THRESHOLD = 1.00; // $1.00
|
|
139
|
+
* const CHECK_INTERVAL = 300000; // 5 minutes
|
|
140
|
+
*
|
|
141
|
+
* setInterval(() => {
|
|
142
|
+
* const costs = db.client.costs;
|
|
143
|
+
*
|
|
144
|
+
* if (costs.total > COST_THRESHOLD) {
|
|
145
|
+
* console.error(`⚠️ Cost threshold exceeded: $${costs.total.toFixed(4)}`);
|
|
146
|
+
* // Send alert (email, Slack, etc.)
|
|
147
|
+
* sendAlert({
|
|
148
|
+
* message: `S3 costs exceeded $${COST_THRESHOLD}`,
|
|
149
|
+
* current: costs.total,
|
|
150
|
+
* breakdown: {
|
|
151
|
+
* requests: costs.requests.subtotal,
|
|
152
|
+
* storage: costs.storage.subtotal,
|
|
153
|
+
* dataTransfer: costs.dataTransfer.subtotal
|
|
154
|
+
* }
|
|
155
|
+
* });
|
|
156
|
+
* }
|
|
157
|
+
* }, CHECK_INTERVAL);
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* ## AWS S3 Pricing Reference
|
|
161
|
+
*
|
|
162
|
+
* ### Request Pricing (us-east-1)
|
|
163
|
+
*
|
|
164
|
+
* | Operation Type | Operations | Price per 1,000 |
|
|
165
|
+
* |----------------|------------|-----------------|
|
|
166
|
+
* | PUT, COPY, POST | PUT, COPY, LIST | $0.005 |
|
|
167
|
+
* | GET, SELECT | GET, HEAD, DELETE | $0.0004 |
|
|
168
|
+
*
|
|
169
|
+
* ### Storage Pricing Tiers (us-east-1, S3 Standard)
|
|
170
|
+
*
|
|
171
|
+
* | Tier | Storage Range | Price per GB/month |
|
|
172
|
+
* |------|---------------|-------------------|
|
|
173
|
+
* | Tier 1 | First 50 TB | $0.023 |
|
|
174
|
+
* | Tier 2 | Next 450 TB | $0.022 |
|
|
175
|
+
* | Tier 3 | Over 500 TB | $0.021 |
|
|
176
|
+
*
|
|
177
|
+
* ### Data Transfer Pricing (Out to Internet)
|
|
178
|
+
*
|
|
179
|
+
* | Tier | Transfer Range | Price per GB |
|
|
180
|
+
* |------|----------------|--------------|
|
|
181
|
+
* | Free Tier | First 100 GB/month | $0.00 (optional) |
|
|
182
|
+
* | Tier 1 | First 10 TB | $0.09 |
|
|
183
|
+
* | Tier 2 | Next 40 TB | $0.085 |
|
|
184
|
+
* | Tier 3 | Next 100 TB | $0.07 |
|
|
185
|
+
* | Tier 4 | Over 150 TB | $0.05 |
|
|
186
|
+
*
|
|
187
|
+
* **Note**: Data transfer IN is always free.
|
|
188
|
+
*
|
|
189
|
+
* ## Best Practices
|
|
190
|
+
*
|
|
191
|
+
* ### 1. Monitor Costs Regularly
|
|
192
|
+
*
|
|
193
|
+
* ```javascript
|
|
194
|
+
* // Daily cost summary
|
|
195
|
+
* function generateDailyCostReport() {
|
|
196
|
+
* const costs = db.client.costs;
|
|
197
|
+
*
|
|
198
|
+
* return {
|
|
199
|
+
* date: new Date().toISOString().split('T')[0],
|
|
200
|
+
* total: costs.total,
|
|
201
|
+
* breakdown: {
|
|
202
|
+
* requests: {
|
|
203
|
+
* count: costs.requests.total,
|
|
204
|
+
* cost: costs.requests.subtotal
|
|
205
|
+
* },
|
|
206
|
+
* storage: {
|
|
207
|
+
* gb: costs.storage.totalGB,
|
|
208
|
+
* cost: costs.storage.subtotal
|
|
209
|
+
* },
|
|
210
|
+
* dataTransfer: {
|
|
211
|
+
* inGB: costs.dataTransfer.inGB,
|
|
212
|
+
* outGB: costs.dataTransfer.outGB,
|
|
213
|
+
* cost: costs.dataTransfer.subtotal
|
|
214
|
+
* }
|
|
215
|
+
* }
|
|
216
|
+
* };
|
|
217
|
+
* }
|
|
218
|
+
*
|
|
219
|
+
* // Schedule daily reports
|
|
220
|
+
* setInterval(() => {
|
|
221
|
+
* const report = generateDailyCostReport();
|
|
222
|
+
* saveCostReport(report);
|
|
223
|
+
* }, 24 * 60 * 60 * 1000);
|
|
224
|
+
* ```
|
|
225
|
+
*
|
|
226
|
+
* ### 2. Optimize Request Patterns
|
|
227
|
+
*
|
|
228
|
+
* ```javascript
|
|
229
|
+
* // EXPENSIVE: Many small operations
|
|
230
|
+
* for (let i = 0; i < 1000; i++) {
|
|
231
|
+
* await users.get(`user-${i}`); // 1000 GET requests = $0.0004
|
|
232
|
+
* }
|
|
233
|
+
*
|
|
234
|
+
* // CHEAPER: Batch operations
|
|
235
|
+
* const ids = Array.from({ length: 1000 }, (_, i) => `user-${i}`);
|
|
236
|
+
* await users.getMany(ids); // Fewer requests, same result
|
|
237
|
+
* ```
|
|
238
|
+
*
|
|
239
|
+
* ### 3. Use Free Tier When Available
|
|
240
|
+
*
|
|
241
|
+
* ```javascript
|
|
242
|
+
* // Enable free tier for development/testing
|
|
243
|
+
* await db.use(new CostsPlugin({
|
|
244
|
+
* considerFreeTier: true // First 100GB data transfer out is free
|
|
245
|
+
* }));
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* ### 4. Track Costs Per Environment
|
|
249
|
+
*
|
|
250
|
+
* ```javascript
|
|
251
|
+
* // Development environment
|
|
252
|
+
* const devDb = new Database({ connectionString: 's3://dev-bucket/db' });
|
|
253
|
+
* await devDb.use(new CostsPlugin({ considerFreeTier: true }));
|
|
254
|
+
*
|
|
255
|
+
* // Production environment
|
|
256
|
+
* const prodDb = new Database({ connectionString: 's3://prod-bucket/db' });
|
|
257
|
+
* await prodDb.use(new CostsPlugin({ considerFreeTier: false }));
|
|
258
|
+
*
|
|
259
|
+
* // Compare costs
|
|
260
|
+
* console.log('Dev costs:', devDb.client.costs.total);
|
|
261
|
+
* console.log('Prod costs:', prodDb.client.costs.total);
|
|
262
|
+
* ```
|
|
263
|
+
*
|
|
264
|
+
* ## Performance Considerations
|
|
265
|
+
*
|
|
266
|
+
* ### Overhead
|
|
267
|
+
*
|
|
268
|
+
* The CostsPlugin adds minimal overhead:
|
|
269
|
+
* - **CPU**: <1% overhead (simple arithmetic operations)
|
|
270
|
+
* - **Memory**: ~2KB for cost tracking objects
|
|
271
|
+
* - **Latency**: No measurable impact on operation latency
|
|
272
|
+
*
|
|
273
|
+
* ### Storage Tracking Accuracy
|
|
274
|
+
*
|
|
275
|
+
* ```javascript
|
|
276
|
+
* // Storage costs are ESTIMATES based on tracked operations
|
|
277
|
+
* // Actual S3 storage may differ due to:
|
|
278
|
+
* // - S3 versioning
|
|
279
|
+
* // - Incomplete multipart uploads
|
|
280
|
+
* // - S3 replication
|
|
281
|
+
* // - External S3 operations not tracked by s3db
|
|
282
|
+
*
|
|
283
|
+
* // For accurate storage costs, use AWS Cost Explorer API
|
|
284
|
+
* ```
|
|
285
|
+
*
|
|
286
|
+
* ## Troubleshooting
|
|
287
|
+
*
|
|
288
|
+
* ### Costs Not Being Tracked
|
|
289
|
+
*
|
|
290
|
+
* ```javascript
|
|
291
|
+
* // Ensure plugin is installed and started
|
|
292
|
+
* console.log(db.plugins.CostsPlugin); // Should exist
|
|
293
|
+
* await db.start(); // Must call start() to activate plugin
|
|
294
|
+
*
|
|
295
|
+
* // Check client costs object
|
|
296
|
+
* console.log(db.client.costs); // Should have costs structure
|
|
297
|
+
* ```
|
|
298
|
+
*
|
|
299
|
+
* ### Inaccurate Cost Calculations
|
|
300
|
+
*
|
|
301
|
+
* ```javascript
|
|
302
|
+
* // Check region configuration
|
|
303
|
+
* const plugin = new CostsPlugin({ region: 'us-east-1' });
|
|
304
|
+
* // Plugin uses us-east-1 pricing by default
|
|
305
|
+
* // For other regions, costs may differ
|
|
306
|
+
*
|
|
307
|
+
* // Verify operation counts
|
|
308
|
+
* console.log(db.client.costs.requests.events);
|
|
309
|
+
* // Should show operation counts
|
|
310
|
+
* ```
|
|
311
|
+
*
|
|
312
|
+
* ### Storage Costs Seem High
|
|
313
|
+
*
|
|
314
|
+
* ```javascript
|
|
315
|
+
* // Storage costs accumulate over time
|
|
316
|
+
* // Check total storage
|
|
317
|
+
* const costs = db.client.costs;
|
|
318
|
+
* console.log(`Total storage: ${costs.storage.totalGB} GB`);
|
|
319
|
+
* console.log(`Current tier: ${costs.storage.currentTier}`);
|
|
320
|
+
* console.log(`Monthly cost: $${costs.storage.subtotal.toFixed(4)}`);
|
|
321
|
+
*
|
|
322
|
+
* // Note: Storage cost is MONTHLY estimate
|
|
323
|
+
* // Divide by 30 for daily estimate
|
|
324
|
+
* const dailyStorageCost = costs.storage.subtotal / 30;
|
|
325
|
+
* console.log(`Daily storage cost: $${dailyStorageCost.toFixed(6)}`);
|
|
326
|
+
* ```
|
|
327
|
+
*
|
|
328
|
+
* ### Free Tier Not Applied
|
|
329
|
+
*
|
|
330
|
+
* ```javascript
|
|
331
|
+
* // Ensure considerFreeTier is enabled
|
|
332
|
+
* await db.use(new CostsPlugin({
|
|
333
|
+
* considerFreeTier: true // Must be explicitly enabled
|
|
334
|
+
* }));
|
|
335
|
+
*
|
|
336
|
+
* // Check free tier usage
|
|
337
|
+
* const costs = db.client.costs;
|
|
338
|
+
* console.log(`Free tier used: ${costs.dataTransfer.freeTierUsed} GB`);
|
|
339
|
+
* console.log(`Free tier available: ${costs.dataTransfer.freeTierGB} GB`);
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* ## Real-World Use Cases
|
|
343
|
+
*
|
|
344
|
+
* ### 1. Development Cost Tracking
|
|
345
|
+
*
|
|
346
|
+
* ```javascript
|
|
347
|
+
* // Track costs during development to estimate production costs
|
|
348
|
+
* const db = new Database({ connectionString: 's3://dev-bucket/db' });
|
|
349
|
+
* await db.use(new CostsPlugin({ considerFreeTier: true }));
|
|
350
|
+
*
|
|
351
|
+
* // Run your application
|
|
352
|
+
* await runDevelopmentWorkload();
|
|
353
|
+
*
|
|
354
|
+
* // Generate cost projection
|
|
355
|
+
* const devCosts = db.client.costs;
|
|
356
|
+
* const projectedMonthlyCost = (devCosts.total / devCosts.requests.total) * expectedMonthlyOperations;
|
|
357
|
+
* console.log(`Projected monthly cost: $${projectedMonthlyCost.toFixed(2)}`);
|
|
358
|
+
* ```
|
|
359
|
+
*
|
|
360
|
+
* ### 2. Cost Attribution by Feature
|
|
361
|
+
*
|
|
362
|
+
* ```javascript
|
|
363
|
+
* // Track costs for different features
|
|
364
|
+
* async function trackFeatureCosts(featureName, operation) {
|
|
365
|
+
* const beforeCosts = { ...db.client.costs };
|
|
366
|
+
*
|
|
367
|
+
* await operation();
|
|
368
|
+
*
|
|
369
|
+
* const afterCosts = db.client.costs;
|
|
370
|
+
* const featureCost = afterCosts.total - beforeCosts.total;
|
|
371
|
+
*
|
|
372
|
+
* console.log(`${featureName} cost: $${featureCost.toFixed(6)}`);
|
|
373
|
+
* return featureCost;
|
|
374
|
+
* }
|
|
375
|
+
*
|
|
376
|
+
* // Use it
|
|
377
|
+
* await trackFeatureCosts('User Registration', async () => {
|
|
378
|
+
* await users.insert({ id: 'u1', name: 'John' });
|
|
379
|
+
* await sendWelcomeEmail('u1');
|
|
380
|
+
* });
|
|
381
|
+
* ```
|
|
382
|
+
*
|
|
383
|
+
* ### 3. Cost-Based Rate Limiting
|
|
384
|
+
*
|
|
385
|
+
* ```javascript
|
|
386
|
+
* // Implement rate limiting based on cost thresholds
|
|
387
|
+
* const HOURLY_COST_LIMIT = 0.10; // $0.10 per hour
|
|
388
|
+
* let hourStartCosts = db.client.costs.total;
|
|
389
|
+
*
|
|
390
|
+
* setInterval(() => {
|
|
391
|
+
* hourStartCosts = db.client.costs.total;
|
|
392
|
+
* }, 60 * 60 * 1000); // Reset hourly
|
|
393
|
+
*
|
|
394
|
+
* async function performOperation() {
|
|
395
|
+
* const currentCosts = db.client.costs.total;
|
|
396
|
+
* const hourlyCost = currentCosts - hourStartCosts;
|
|
397
|
+
*
|
|
398
|
+
* if (hourlyCost > HOURLY_COST_LIMIT) {
|
|
399
|
+
* throw new Error('Hourly cost limit exceeded');
|
|
400
|
+
* }
|
|
401
|
+
*
|
|
402
|
+
* // Proceed with operation
|
|
403
|
+
* await resource.insert(data);
|
|
404
|
+
* }
|
|
405
|
+
* ```
|
|
406
|
+
*
|
|
407
|
+
* ### 4. Multi-Tenant Cost Tracking
|
|
408
|
+
*
|
|
409
|
+
* ```javascript
|
|
410
|
+
* // Track costs per tenant using separate database instances
|
|
411
|
+
* const tenantDatabases = {};
|
|
412
|
+
*
|
|
413
|
+
* async function getTenantDatabase(tenantId) {
|
|
414
|
+
* if (!tenantDatabases[tenantId]) {
|
|
415
|
+
* const db = new Database({
|
|
416
|
+
* connectionString: `s3://bucket/tenants/${tenantId}`
|
|
417
|
+
* });
|
|
418
|
+
* await db.use(new CostsPlugin());
|
|
419
|
+
* await db.start();
|
|
420
|
+
* tenantDatabases[tenantId] = db;
|
|
421
|
+
* }
|
|
422
|
+
* return tenantDatabases[tenantId];
|
|
423
|
+
* }
|
|
424
|
+
*
|
|
425
|
+
* // Generate per-tenant cost reports
|
|
426
|
+
* function generateTenantCostReport() {
|
|
427
|
+
* return Object.entries(tenantDatabases).map(([tenantId, db]) => ({
|
|
428
|
+
* tenantId,
|
|
429
|
+
* costs: db.client.costs.total,
|
|
430
|
+
* operations: db.client.costs.requests.total
|
|
431
|
+
* }));
|
|
432
|
+
* }
|
|
433
|
+
* ```
|
|
434
|
+
*
|
|
435
|
+
* ## API Reference
|
|
436
|
+
*
|
|
437
|
+
* ### Constructor Options
|
|
438
|
+
*
|
|
439
|
+
* - `considerFreeTier` (boolean, default: false) - Apply AWS free tier (100GB data transfer)
|
|
440
|
+
* - `region` (string, default: 'us-east-1') - AWS region for pricing
|
|
441
|
+
*
|
|
442
|
+
* ### Cost Object Structure
|
|
443
|
+
*
|
|
444
|
+
* ```typescript
|
|
445
|
+
* interface Costs {
|
|
446
|
+
* total: number;
|
|
447
|
+
*
|
|
448
|
+
* requests: {
|
|
449
|
+
* total: number;
|
|
450
|
+
* totalEvents: number;
|
|
451
|
+
* subtotal: number;
|
|
452
|
+
* counts: {
|
|
453
|
+
* put: number;
|
|
454
|
+
* get: number;
|
|
455
|
+
* copy: number;
|
|
456
|
+
* list: number;
|
|
457
|
+
* delete: number;
|
|
458
|
+
* head: number;
|
|
459
|
+
* post: number;
|
|
460
|
+
* select: number;
|
|
461
|
+
* };
|
|
462
|
+
* events: {
|
|
463
|
+
* PutObjectCommand: number;
|
|
464
|
+
* GetObjectCommand: number;
|
|
465
|
+
* CopyObjectCommand: number;
|
|
466
|
+
* HeadObjectCommand: number;
|
|
467
|
+
* DeleteObjectCommand: number;
|
|
468
|
+
* DeleteObjectsCommand: number;
|
|
469
|
+
* ListObjectsV2Command: number;
|
|
470
|
+
* };
|
|
471
|
+
* prices: {
|
|
472
|
+
* put: number;
|
|
473
|
+
* get: number;
|
|
474
|
+
* copy: number;
|
|
475
|
+
* list: number;
|
|
476
|
+
* delete: number;
|
|
477
|
+
* head: number;
|
|
478
|
+
* };
|
|
479
|
+
* };
|
|
480
|
+
*
|
|
481
|
+
* storage: {
|
|
482
|
+
* totalBytes: number;
|
|
483
|
+
* totalGB: number;
|
|
484
|
+
* currentTier: number;
|
|
485
|
+
* subtotal: number;
|
|
486
|
+
* tiers: Array<{ limit: number; pricePerGB: number }>;
|
|
487
|
+
* };
|
|
488
|
+
*
|
|
489
|
+
* dataTransfer: {
|
|
490
|
+
* inBytes: number;
|
|
491
|
+
* inGB: number;
|
|
492
|
+
* inCost: number; // Always 0
|
|
493
|
+
* outBytes: number;
|
|
494
|
+
* outGB: number;
|
|
495
|
+
* freeTierGB: number;
|
|
496
|
+
* freeTierUsed: number;
|
|
497
|
+
* currentTier: number;
|
|
498
|
+
* subtotal: number;
|
|
499
|
+
* tiers: Array<{ limit: number; pricePerGB: number }>;
|
|
500
|
+
* };
|
|
501
|
+
* }
|
|
502
|
+
* ```
|
|
503
|
+
*
|
|
504
|
+
* ### Accessing Costs
|
|
505
|
+
*
|
|
506
|
+
* ```javascript
|
|
507
|
+
* // From database client
|
|
508
|
+
* const costs = db.client.costs;
|
|
509
|
+
*
|
|
510
|
+
* // From plugin instance (same object)
|
|
511
|
+
* const costsPlugin = db.plugins.CostsPlugin;
|
|
512
|
+
* const costs2 = costsPlugin.costs; // Same as db.client.costs
|
|
513
|
+
* ```
|
|
514
|
+
*
|
|
515
|
+
* ## Notes
|
|
516
|
+
*
|
|
517
|
+
* - Pricing is based on AWS S3 Standard storage class in us-east-1
|
|
518
|
+
* - Storage costs are monthly estimates based on accumulated data size
|
|
519
|
+
* - Data transfer IN is always free (AWS policy)
|
|
520
|
+
* - Free tier is optional and shared across ALL AWS services (not just S3)
|
|
521
|
+
* - Costs are tracked from plugin installation - reset requires new plugin instance
|
|
522
|
+
* - Plugin tracks operations through s3db.js only - external S3 operations not tracked
|
|
523
|
+
*/
|
|
524
|
+
|
|
1
525
|
import { Plugin } from './plugin.class.js';
|
|
2
526
|
|
|
3
527
|
export class CostsPlugin extends Plugin {
|