s3db.js 9.3.0 → 10.0.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/dist/s3db.es.js CHANGED
@@ -419,8 +419,14 @@ function mapAwsError(err, context = {}) {
419
419
  suggestion = "Check if the object metadata is present and valid.";
420
420
  return new MissingMetadata({ ...context, original: err, metadata, commandName, commandInput, suggestion });
421
421
  }
422
- suggestion = "Check the error details and AWS documentation.";
423
- return new UnknownError("Unknown error", { ...context, original: err, metadata, commandName, commandInput, suggestion });
422
+ const errorDetails = [
423
+ `Unknown error: ${err.message || err.toString()}`,
424
+ err.code && `Code: ${err.code}`,
425
+ err.statusCode && `Status: ${err.statusCode}`,
426
+ err.stack && `Stack: ${err.stack.split("\n")[0]}`
427
+ ].filter(Boolean).join(" | ");
428
+ suggestion = `Check the error details and AWS documentation. Original error: ${err.message || err.toString()}`;
429
+ return new UnknownError(errorDetails, { ...context, original: err, metadata, commandName, commandInput, suggestion });
424
430
  }
425
431
  class ConnectionStringError extends S3dbError {
426
432
  constructor(message, details = {}) {
@@ -1899,7 +1905,7 @@ class BackupPlugin extends Plugin {
1899
1905
  include: options.include || null,
1900
1906
  exclude: options.exclude || [],
1901
1907
  backupMetadataResource: options.backupMetadataResource || "backup_metadata",
1902
- tempDir: options.tempDir || "./tmp/backups",
1908
+ tempDir: options.tempDir || "/tmp/s3db/backups",
1903
1909
  verbose: options.verbose || false,
1904
1910
  // Hooks
1905
1911
  onBackupStart: options.onBackupStart || null,
@@ -4046,6 +4052,457 @@ const CostsPlugin = {
4046
4052
  }
4047
4053
  };
4048
4054
 
4055
+ class EventualConsistencyPlugin extends Plugin {
4056
+ constructor(options = {}) {
4057
+ super(options);
4058
+ if (!options.resource) {
4059
+ throw new Error("EventualConsistencyPlugin requires 'resource' option");
4060
+ }
4061
+ if (!options.field) {
4062
+ throw new Error("EventualConsistencyPlugin requires 'field' option");
4063
+ }
4064
+ this.config = {
4065
+ resource: options.resource,
4066
+ field: options.field,
4067
+ cohort: {
4068
+ interval: options.cohort?.interval || "24h",
4069
+ timezone: options.cohort?.timezone || "UTC",
4070
+ ...options.cohort
4071
+ },
4072
+ reducer: options.reducer || ((transactions) => {
4073
+ let baseValue = 0;
4074
+ for (const t of transactions) {
4075
+ if (t.operation === "set") {
4076
+ baseValue = t.value;
4077
+ } else if (t.operation === "add") {
4078
+ baseValue += t.value;
4079
+ } else if (t.operation === "sub") {
4080
+ baseValue -= t.value;
4081
+ }
4082
+ }
4083
+ return baseValue;
4084
+ }),
4085
+ consolidationInterval: options.consolidationInterval || 36e5,
4086
+ // 1 hour default
4087
+ autoConsolidate: options.autoConsolidate !== false,
4088
+ batchTransactions: options.batchTransactions || false,
4089
+ batchSize: options.batchSize || 100,
4090
+ mode: options.mode || "async",
4091
+ // 'async' or 'sync'
4092
+ ...options
4093
+ };
4094
+ this.transactionResource = null;
4095
+ this.targetResource = null;
4096
+ this.consolidationTimer = null;
4097
+ this.pendingTransactions = /* @__PURE__ */ new Map();
4098
+ }
4099
+ async onSetup() {
4100
+ this.targetResource = this.database.resources[this.config.resource];
4101
+ if (!this.targetResource) {
4102
+ this.deferredSetup = true;
4103
+ this.watchForResource();
4104
+ return;
4105
+ }
4106
+ await this.completeSetup();
4107
+ }
4108
+ watchForResource() {
4109
+ const hookCallback = async ({ resource, config }) => {
4110
+ if (config.name === this.config.resource && this.deferredSetup) {
4111
+ this.targetResource = resource;
4112
+ this.deferredSetup = false;
4113
+ await this.completeSetup();
4114
+ }
4115
+ };
4116
+ this.database.addHook("afterCreateResource", hookCallback);
4117
+ }
4118
+ async completeSetup() {
4119
+ if (!this.targetResource) return;
4120
+ const transactionResourceName = `${this.config.resource}_transactions_${this.config.field}`;
4121
+ const partitionConfig = this.createPartitionConfig();
4122
+ const [ok, err, transactionResource] = await tryFn(
4123
+ () => this.database.createResource({
4124
+ name: transactionResourceName,
4125
+ attributes: {
4126
+ id: "string|required",
4127
+ originalId: "string|required",
4128
+ field: "string|required",
4129
+ value: "number|required",
4130
+ operation: "string|required",
4131
+ // 'set', 'add', or 'sub'
4132
+ timestamp: "string|required",
4133
+ cohortDate: "string|required",
4134
+ // For partitioning
4135
+ cohortMonth: "string|optional",
4136
+ // For monthly partitioning
4137
+ source: "string|optional",
4138
+ applied: "boolean|optional"
4139
+ // Track if transaction was applied
4140
+ },
4141
+ behavior: "body-overflow",
4142
+ timestamps: true,
4143
+ partitions: partitionConfig,
4144
+ asyncPartitions: true
4145
+ // Use async partitions for better performance
4146
+ })
4147
+ );
4148
+ if (!ok && !this.database.resources[transactionResourceName]) {
4149
+ throw new Error(`Failed to create transaction resource: ${err?.message}`);
4150
+ }
4151
+ this.transactionResource = ok ? transactionResource : this.database.resources[transactionResourceName];
4152
+ this.addHelperMethods();
4153
+ if (this.config.autoConsolidate) {
4154
+ this.startConsolidationTimer();
4155
+ }
4156
+ }
4157
+ async onStart() {
4158
+ if (this.deferredSetup) {
4159
+ return;
4160
+ }
4161
+ this.emit("eventual-consistency.started", {
4162
+ resource: this.config.resource,
4163
+ field: this.config.field,
4164
+ cohort: this.config.cohort
4165
+ });
4166
+ }
4167
+ async onStop() {
4168
+ if (this.consolidationTimer) {
4169
+ clearInterval(this.consolidationTimer);
4170
+ this.consolidationTimer = null;
4171
+ }
4172
+ await this.flushPendingTransactions();
4173
+ this.emit("eventual-consistency.stopped", {
4174
+ resource: this.config.resource,
4175
+ field: this.config.field
4176
+ });
4177
+ }
4178
+ createPartitionConfig() {
4179
+ const partitions = {
4180
+ byDay: {
4181
+ fields: {
4182
+ cohortDate: "string"
4183
+ }
4184
+ },
4185
+ byMonth: {
4186
+ fields: {
4187
+ cohortMonth: "string"
4188
+ }
4189
+ }
4190
+ };
4191
+ return partitions;
4192
+ }
4193
+ addHelperMethods() {
4194
+ const resource = this.targetResource;
4195
+ const defaultField = this.config.field;
4196
+ const plugin = this;
4197
+ if (!resource._eventualConsistencyPlugins) {
4198
+ resource._eventualConsistencyPlugins = {};
4199
+ }
4200
+ resource._eventualConsistencyPlugins[defaultField] = plugin;
4201
+ resource.set = async (id, fieldOrValue, value) => {
4202
+ const hasMultipleFields = Object.keys(resource._eventualConsistencyPlugins).length > 1;
4203
+ if (hasMultipleFields && value === void 0) {
4204
+ throw new Error(`Multiple fields have eventual consistency. Please specify the field: set(id, field, value)`);
4205
+ }
4206
+ const field = value !== void 0 ? fieldOrValue : defaultField;
4207
+ const actualValue = value !== void 0 ? value : fieldOrValue;
4208
+ const fieldPlugin = resource._eventualConsistencyPlugins[field];
4209
+ if (!fieldPlugin) {
4210
+ throw new Error(`No eventual consistency plugin found for field "${field}"`);
4211
+ }
4212
+ await fieldPlugin.createTransaction({
4213
+ originalId: id,
4214
+ operation: "set",
4215
+ value: actualValue,
4216
+ source: "set"
4217
+ });
4218
+ if (fieldPlugin.config.mode === "sync") {
4219
+ const consolidatedValue = await fieldPlugin.consolidateRecord(id);
4220
+ await resource.update(id, {
4221
+ [field]: consolidatedValue
4222
+ });
4223
+ return consolidatedValue;
4224
+ }
4225
+ return actualValue;
4226
+ };
4227
+ resource.add = async (id, fieldOrAmount, amount) => {
4228
+ const hasMultipleFields = Object.keys(resource._eventualConsistencyPlugins).length > 1;
4229
+ if (hasMultipleFields && amount === void 0) {
4230
+ throw new Error(`Multiple fields have eventual consistency. Please specify the field: add(id, field, amount)`);
4231
+ }
4232
+ const field = amount !== void 0 ? fieldOrAmount : defaultField;
4233
+ const actualAmount = amount !== void 0 ? amount : fieldOrAmount;
4234
+ const fieldPlugin = resource._eventualConsistencyPlugins[field];
4235
+ if (!fieldPlugin) {
4236
+ throw new Error(`No eventual consistency plugin found for field "${field}"`);
4237
+ }
4238
+ await fieldPlugin.createTransaction({
4239
+ originalId: id,
4240
+ operation: "add",
4241
+ value: actualAmount,
4242
+ source: "add"
4243
+ });
4244
+ if (fieldPlugin.config.mode === "sync") {
4245
+ const consolidatedValue = await fieldPlugin.consolidateRecord(id);
4246
+ await resource.update(id, {
4247
+ [field]: consolidatedValue
4248
+ });
4249
+ return consolidatedValue;
4250
+ }
4251
+ const currentValue = await fieldPlugin.getConsolidatedValue(id);
4252
+ return currentValue + actualAmount;
4253
+ };
4254
+ resource.sub = async (id, fieldOrAmount, amount) => {
4255
+ const hasMultipleFields = Object.keys(resource._eventualConsistencyPlugins).length > 1;
4256
+ if (hasMultipleFields && amount === void 0) {
4257
+ throw new Error(`Multiple fields have eventual consistency. Please specify the field: sub(id, field, amount)`);
4258
+ }
4259
+ const field = amount !== void 0 ? fieldOrAmount : defaultField;
4260
+ const actualAmount = amount !== void 0 ? amount : fieldOrAmount;
4261
+ const fieldPlugin = resource._eventualConsistencyPlugins[field];
4262
+ if (!fieldPlugin) {
4263
+ throw new Error(`No eventual consistency plugin found for field "${field}"`);
4264
+ }
4265
+ await fieldPlugin.createTransaction({
4266
+ originalId: id,
4267
+ operation: "sub",
4268
+ value: actualAmount,
4269
+ source: "sub"
4270
+ });
4271
+ if (fieldPlugin.config.mode === "sync") {
4272
+ const consolidatedValue = await fieldPlugin.consolidateRecord(id);
4273
+ await resource.update(id, {
4274
+ [field]: consolidatedValue
4275
+ });
4276
+ return consolidatedValue;
4277
+ }
4278
+ const currentValue = await fieldPlugin.getConsolidatedValue(id);
4279
+ return currentValue - actualAmount;
4280
+ };
4281
+ resource.consolidate = async (id, field) => {
4282
+ const hasMultipleFields = Object.keys(resource._eventualConsistencyPlugins).length > 1;
4283
+ if (hasMultipleFields && !field) {
4284
+ throw new Error(`Multiple fields have eventual consistency. Please specify the field: consolidate(id, field)`);
4285
+ }
4286
+ const actualField = field || defaultField;
4287
+ const fieldPlugin = resource._eventualConsistencyPlugins[actualField];
4288
+ if (!fieldPlugin) {
4289
+ throw new Error(`No eventual consistency plugin found for field "${actualField}"`);
4290
+ }
4291
+ return await fieldPlugin.consolidateRecord(id);
4292
+ };
4293
+ resource.getConsolidatedValue = async (id, fieldOrOptions, options) => {
4294
+ if (typeof fieldOrOptions === "string") {
4295
+ const field = fieldOrOptions;
4296
+ const fieldPlugin = resource._eventualConsistencyPlugins[field] || plugin;
4297
+ return await fieldPlugin.getConsolidatedValue(id, options || {});
4298
+ } else {
4299
+ return await plugin.getConsolidatedValue(id, fieldOrOptions || {});
4300
+ }
4301
+ };
4302
+ }
4303
+ async createTransaction(data) {
4304
+ const now = /* @__PURE__ */ new Date();
4305
+ const cohortInfo = this.getCohortInfo(now);
4306
+ const transaction = {
4307
+ id: `txn-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
4308
+ originalId: data.originalId,
4309
+ field: this.config.field,
4310
+ value: data.value || 0,
4311
+ operation: data.operation || "set",
4312
+ timestamp: now.toISOString(),
4313
+ cohortDate: cohortInfo.date,
4314
+ cohortMonth: cohortInfo.month,
4315
+ source: data.source || "unknown",
4316
+ applied: false
4317
+ };
4318
+ if (this.config.batchTransactions) {
4319
+ this.pendingTransactions.set(transaction.id, transaction);
4320
+ if (this.pendingTransactions.size >= this.config.batchSize) {
4321
+ await this.flushPendingTransactions();
4322
+ }
4323
+ } else {
4324
+ await this.transactionResource.insert(transaction);
4325
+ }
4326
+ return transaction;
4327
+ }
4328
+ async flushPendingTransactions() {
4329
+ if (this.pendingTransactions.size === 0) return;
4330
+ const transactions = Array.from(this.pendingTransactions.values());
4331
+ this.pendingTransactions.clear();
4332
+ for (const transaction of transactions) {
4333
+ await this.transactionResource.insert(transaction);
4334
+ }
4335
+ }
4336
+ getCohortInfo(date) {
4337
+ const tz = this.config.cohort.timezone;
4338
+ const offset = this.getTimezoneOffset(tz);
4339
+ const localDate = new Date(date.getTime() + offset);
4340
+ const year = localDate.getFullYear();
4341
+ const month = String(localDate.getMonth() + 1).padStart(2, "0");
4342
+ const day = String(localDate.getDate()).padStart(2, "0");
4343
+ return {
4344
+ date: `${year}-${month}-${day}`,
4345
+ month: `${year}-${month}`
4346
+ };
4347
+ }
4348
+ getTimezoneOffset(timezone) {
4349
+ const offsets = {
4350
+ "UTC": 0,
4351
+ "America/New_York": -5 * 36e5,
4352
+ "America/Chicago": -6 * 36e5,
4353
+ "America/Denver": -7 * 36e5,
4354
+ "America/Los_Angeles": -8 * 36e5,
4355
+ "America/Sao_Paulo": -3 * 36e5,
4356
+ "Europe/London": 0,
4357
+ "Europe/Paris": 1 * 36e5,
4358
+ "Europe/Berlin": 1 * 36e5,
4359
+ "Asia/Tokyo": 9 * 36e5,
4360
+ "Asia/Shanghai": 8 * 36e5,
4361
+ "Australia/Sydney": 10 * 36e5
4362
+ };
4363
+ return offsets[timezone] || 0;
4364
+ }
4365
+ startConsolidationTimer() {
4366
+ const interval = this.config.consolidationInterval;
4367
+ this.consolidationTimer = setInterval(async () => {
4368
+ await this.runConsolidation();
4369
+ }, interval);
4370
+ }
4371
+ async runConsolidation() {
4372
+ try {
4373
+ const [ok, err, transactions] = await tryFn(
4374
+ () => this.transactionResource.query({
4375
+ applied: false
4376
+ })
4377
+ );
4378
+ if (!ok) {
4379
+ console.error("Consolidation failed to query transactions:", err);
4380
+ return;
4381
+ }
4382
+ const uniqueIds = [...new Set(transactions.map((t) => t.originalId))];
4383
+ for (const id of uniqueIds) {
4384
+ await this.consolidateRecord(id);
4385
+ }
4386
+ this.emit("eventual-consistency.consolidated", {
4387
+ resource: this.config.resource,
4388
+ field: this.config.field,
4389
+ recordCount: uniqueIds.length
4390
+ });
4391
+ } catch (error) {
4392
+ console.error("Consolidation error:", error);
4393
+ this.emit("eventual-consistency.consolidation-error", error);
4394
+ }
4395
+ }
4396
+ async consolidateRecord(originalId) {
4397
+ const [recordOk, recordErr, record] = await tryFn(
4398
+ () => this.targetResource.get(originalId)
4399
+ );
4400
+ const currentValue = recordOk && record ? record[this.config.field] || 0 : 0;
4401
+ const [ok, err, transactions] = await tryFn(
4402
+ () => this.transactionResource.query({
4403
+ originalId,
4404
+ applied: false
4405
+ })
4406
+ );
4407
+ if (!ok || !transactions || transactions.length === 0) {
4408
+ return currentValue;
4409
+ }
4410
+ transactions.sort(
4411
+ (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
4412
+ );
4413
+ const hasSetOperation = transactions.some((t) => t.operation === "set");
4414
+ if (currentValue !== 0 && !hasSetOperation) {
4415
+ transactions.unshift({
4416
+ id: "__synthetic__",
4417
+ // Synthetic ID that we'll skip when marking as applied
4418
+ operation: "set",
4419
+ value: currentValue,
4420
+ timestamp: (/* @__PURE__ */ new Date(0)).toISOString()
4421
+ // Very old timestamp to ensure it's first
4422
+ });
4423
+ }
4424
+ const consolidatedValue = this.config.reducer(transactions);
4425
+ const [updateOk, updateErr] = await tryFn(
4426
+ () => this.targetResource.update(originalId, {
4427
+ [this.config.field]: consolidatedValue
4428
+ })
4429
+ );
4430
+ if (updateOk) {
4431
+ for (const txn of transactions) {
4432
+ if (txn.id !== "__synthetic__") {
4433
+ await this.transactionResource.update(txn.id, {
4434
+ applied: true
4435
+ });
4436
+ }
4437
+ }
4438
+ }
4439
+ return consolidatedValue;
4440
+ }
4441
+ async getConsolidatedValue(originalId, options = {}) {
4442
+ const includeApplied = options.includeApplied || false;
4443
+ const startDate = options.startDate;
4444
+ const endDate = options.endDate;
4445
+ const query = { originalId };
4446
+ if (!includeApplied) {
4447
+ query.applied = false;
4448
+ }
4449
+ const [ok, err, transactions] = await tryFn(
4450
+ () => this.transactionResource.query(query)
4451
+ );
4452
+ if (!ok || !transactions || transactions.length === 0) {
4453
+ const [recordOk, recordErr, record] = await tryFn(
4454
+ () => this.targetResource.get(originalId)
4455
+ );
4456
+ if (recordOk && record) {
4457
+ return record[this.config.field] || 0;
4458
+ }
4459
+ return 0;
4460
+ }
4461
+ let filtered = transactions;
4462
+ if (startDate || endDate) {
4463
+ filtered = transactions.filter((t) => {
4464
+ const timestamp = new Date(t.timestamp);
4465
+ if (startDate && timestamp < new Date(startDate)) return false;
4466
+ if (endDate && timestamp > new Date(endDate)) return false;
4467
+ return true;
4468
+ });
4469
+ }
4470
+ filtered.sort(
4471
+ (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
4472
+ );
4473
+ return this.config.reducer(filtered);
4474
+ }
4475
+ // Helper method to get cohort statistics
4476
+ async getCohortStats(cohortDate) {
4477
+ const [ok, err, transactions] = await tryFn(
4478
+ () => this.transactionResource.query({
4479
+ cohortDate
4480
+ })
4481
+ );
4482
+ if (!ok) return null;
4483
+ const stats = {
4484
+ date: cohortDate,
4485
+ transactionCount: transactions.length,
4486
+ totalValue: 0,
4487
+ byOperation: { set: 0, add: 0, sub: 0 },
4488
+ byOriginalId: {}
4489
+ };
4490
+ for (const txn of transactions) {
4491
+ stats.totalValue += txn.value || 0;
4492
+ stats.byOperation[txn.operation] = (stats.byOperation[txn.operation] || 0) + 1;
4493
+ if (!stats.byOriginalId[txn.originalId]) {
4494
+ stats.byOriginalId[txn.originalId] = {
4495
+ count: 0,
4496
+ value: 0
4497
+ };
4498
+ }
4499
+ stats.byOriginalId[txn.originalId].count++;
4500
+ stats.byOriginalId[txn.originalId].value += txn.value || 0;
4501
+ }
4502
+ return stats;
4503
+ }
4504
+ }
4505
+
4049
4506
  class FullTextPlugin extends Plugin {
4050
4507
  constructor(options = {}) {
4051
4508
  super();
@@ -5830,10 +6287,10 @@ class Client extends EventEmitter {
5830
6287
  // Enabled for better performance
5831
6288
  keepAliveMsecs: 1e3,
5832
6289
  // 1 second keep-alive
5833
- maxSockets: 50,
5834
- // Balanced for most applications
5835
- maxFreeSockets: 10,
5836
- // Good connection reuse
6290
+ maxSockets: httpClientOptions.maxSockets || 500,
6291
+ // High concurrency support
6292
+ maxFreeSockets: httpClientOptions.maxFreeSockets || 100,
6293
+ // Better connection reuse
5837
6294
  timeout: 6e4,
5838
6295
  // 60 second timeout
5839
6296
  ...httpClientOptions
@@ -9696,7 +10153,7 @@ class Database extends EventEmitter {
9696
10153
  this.id = idGenerator(7);
9697
10154
  this.version = "1";
9698
10155
  this.s3dbVersion = (() => {
9699
- const [ok, err, version] = tryFn(() => true ? "9.3.0" : "latest");
10156
+ const [ok, err, version] = tryFn(() => true ? "10.0.0" : "latest");
9700
10157
  return ok ? version : "latest";
9701
10158
  })();
9702
10159
  this.resources = {};
@@ -12765,5 +13222,5 @@ class StateMachinePlugin extends Plugin {
12765
13222
  }
12766
13223
  }
12767
13224
 
12768
- export { AVAILABLE_BEHAVIORS, AuditPlugin, AuthenticationError, BackupPlugin, BaseError, CachePlugin, Client, ConnectionString, ConnectionStringError, CostsPlugin, CryptoError, DEFAULT_BEHAVIOR, Database, DatabaseError, EncryptionError, ErrorMap, FullTextPlugin, InvalidResourceItem, MetricsPlugin, MissingMetadata, NoSuchBucket, NoSuchKey, NotFound, PartitionError, PermissionError, Plugin, PluginObject, ReplicatorPlugin, Resource, ResourceError, ResourceIdsPageReader, ResourceIdsReader, ResourceNotFound, ResourceReader, ResourceWriter, Database as S3db, S3dbError, SchedulerPlugin, Schema, SchemaError, StateMachinePlugin, UnknownError, ValidationError, Validator, behaviors, calculateAttributeNamesSize, calculateAttributeSizes, calculateEffectiveLimit, calculateSystemOverhead, calculateTotalSize, calculateUTF8Bytes, clearUTF8Cache, clearUTF8Memo, clearUTF8Memory, decode, decodeDecimal, decrypt, S3db as default, encode, encodeDecimal, encrypt, getBehavior, getSizeBreakdown, idGenerator, mapAwsError, md5, passwordGenerator, sha256, streamToString, transformValue, tryFn, tryFnSync };
13225
+ export { AVAILABLE_BEHAVIORS, AuditPlugin, AuthenticationError, BackupPlugin, BaseError, CachePlugin, Client, ConnectionString, ConnectionStringError, CostsPlugin, CryptoError, DEFAULT_BEHAVIOR, Database, DatabaseError, EncryptionError, ErrorMap, EventualConsistencyPlugin, FullTextPlugin, InvalidResourceItem, MetricsPlugin, MissingMetadata, NoSuchBucket, NoSuchKey, NotFound, PartitionError, PermissionError, Plugin, PluginObject, ReplicatorPlugin, Resource, ResourceError, ResourceIdsPageReader, ResourceIdsReader, ResourceNotFound, ResourceReader, ResourceWriter, Database as S3db, S3dbError, SchedulerPlugin, Schema, SchemaError, StateMachinePlugin, UnknownError, ValidationError, Validator, behaviors, calculateAttributeNamesSize, calculateAttributeSizes, calculateEffectiveLimit, calculateSystemOverhead, calculateTotalSize, calculateUTF8Bytes, clearUTF8Cache, clearUTF8Memo, clearUTF8Memory, decode, decodeDecimal, decrypt, S3db as default, encode, encodeDecimal, encrypt, getBehavior, getSizeBreakdown, idGenerator, mapAwsError, md5, passwordGenerator, sha256, streamToString, transformValue, tryFn, tryFnSync };
12769
13226
  //# sourceMappingURL=s3db.es.js.map