s3db.js 4.1.8 → 4.1.10

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.cjs.js CHANGED
@@ -9269,6 +9269,58 @@ class Resource extends EventEmitter {
9269
9269
  this.emit("get", data);
9270
9270
  return data;
9271
9271
  } catch (error) {
9272
+ if (error.message.includes("Cipher job failed") || error.message.includes("OperationError") || error.originalError?.message?.includes("Cipher job failed")) {
9273
+ try {
9274
+ console.warn(`Decryption failed for resource ${id}, attempting to get raw metadata`);
9275
+ const request = await this.client.headObject(key);
9276
+ const objectVersion = this.extractVersionFromKey(key) || this.version;
9277
+ const tempSchema = new Schema({
9278
+ name: this.name,
9279
+ attributes: this.attributes,
9280
+ passphrase: this.passphrase,
9281
+ version: objectVersion,
9282
+ options: {
9283
+ ...this.options,
9284
+ autoDecrypt: false,
9285
+ // Disable decryption
9286
+ autoEncrypt: false
9287
+ // Disable encryption
9288
+ }
9289
+ });
9290
+ let metadata = await tempSchema.unmapper(request.Metadata);
9291
+ const behaviorImpl = getBehavior(this.behavior);
9292
+ let body = "";
9293
+ if (request.ContentLength > 0) {
9294
+ try {
9295
+ const fullObject = await this.client.getObject(key);
9296
+ body = await streamToString(fullObject.Body);
9297
+ } catch (bodyError) {
9298
+ console.warn(`Failed to read body for resource ${id}:`, bodyError.message);
9299
+ body = "";
9300
+ }
9301
+ }
9302
+ const { metadata: processedMetadata } = await behaviorImpl.handleGet({
9303
+ resource: this,
9304
+ metadata,
9305
+ body
9306
+ });
9307
+ let data = processedMetadata;
9308
+ data.id = id;
9309
+ data._contentLength = request.ContentLength;
9310
+ data._lastModified = request.LastModified;
9311
+ data._hasContent = request.ContentLength > 0;
9312
+ data._mimeType = request.ContentType || null;
9313
+ data._version = objectVersion;
9314
+ data._decryptionFailed = true;
9315
+ if (request.VersionId) data._versionId = request.VersionId;
9316
+ if (request.Expiration) data._expiresAt = request.Expiration;
9317
+ data._definitionHash = this.getDefinitionHash();
9318
+ this.emit("get", data);
9319
+ return data;
9320
+ } catch (fallbackError) {
9321
+ console.error(`Fallback attempt also failed for resource ${id}:`, fallbackError.message);
9322
+ }
9323
+ }
9272
9324
  const enhancedError = new Error(`Failed to get resource with id '${id}': ${error.message}`);
9273
9325
  enhancedError.originalError = error;
9274
9326
  enhancedError.resourceId = id;
@@ -9658,11 +9710,27 @@ class Resource extends EventEmitter {
9658
9710
  if (limit) {
9659
9711
  filteredIds2 = filteredIds2.slice(0, limit);
9660
9712
  }
9661
- const { results: results2 } = await promisePool.PromisePool.for(filteredIds2).withConcurrency(this.parallelism).process(async (id) => {
9662
- return await this.get(id);
9713
+ const { results: results2, errors: errors2 } = await promisePool.PromisePool.for(filteredIds2).withConcurrency(this.parallelism).handleError(async (error, id) => {
9714
+ console.warn(`Failed to get resource ${id}:`, error.message);
9715
+ return null;
9716
+ }).process(async (id) => {
9717
+ try {
9718
+ return await this.get(id);
9719
+ } catch (error) {
9720
+ if (error.message.includes("Cipher job failed") || error.message.includes("OperationError")) {
9721
+ console.warn(`Decryption failed for ${id}, returning basic info`);
9722
+ return {
9723
+ id,
9724
+ _decryptionFailed: true,
9725
+ _error: error.message
9726
+ };
9727
+ }
9728
+ throw error;
9729
+ }
9663
9730
  });
9664
- this.emit("list", { partition, partitionValues, count: results2.length });
9665
- return results2;
9731
+ const validResults2 = results2.filter((item) => item !== null);
9732
+ this.emit("list", { partition, partitionValues, count: validResults2.length, errors: errors2.length });
9733
+ return validResults2;
9666
9734
  }
9667
9735
  const partitionDef = this.options.partitions[partition];
9668
9736
  if (!partitionDef) {
@@ -9693,11 +9761,29 @@ class Resource extends EventEmitter {
9693
9761
  if (limit) {
9694
9762
  filteredIds = filteredIds.slice(0, limit);
9695
9763
  }
9696
- const { results } = await promisePool.PromisePool.for(filteredIds).withConcurrency(this.parallelism).process(async (id) => {
9697
- return await this.getFromPartition({ id, partitionName: partition, partitionValues });
9764
+ const { results, errors } = await promisePool.PromisePool.for(filteredIds).withConcurrency(this.parallelism).handleError(async (error, id) => {
9765
+ console.warn(`Failed to get partition resource ${id}:`, error.message);
9766
+ return null;
9767
+ }).process(async (id) => {
9768
+ try {
9769
+ return await this.getFromPartition({ id, partitionName: partition, partitionValues });
9770
+ } catch (error) {
9771
+ if (error.message.includes("Cipher job failed") || error.message.includes("OperationError")) {
9772
+ console.warn(`Decryption failed for partition resource ${id}, returning basic info`);
9773
+ return {
9774
+ id,
9775
+ _partition: partition,
9776
+ _partitionValues: partitionValues,
9777
+ _decryptionFailed: true,
9778
+ _error: error.message
9779
+ };
9780
+ }
9781
+ throw error;
9782
+ }
9698
9783
  });
9699
- this.emit("list", { partition, partitionValues, count: results.length });
9700
- return results;
9784
+ const validResults = results.filter((item) => item !== null);
9785
+ this.emit("list", { partition, partitionValues, count: validResults.length, errors: errors.length });
9786
+ return validResults;
9701
9787
  }
9702
9788
  /**
9703
9789
  * Get multiple resources by their IDs
@@ -9708,11 +9794,30 @@ class Resource extends EventEmitter {
9708
9794
  * users.forEach(user => console.log(user.name));
9709
9795
  */
9710
9796
  async getMany(ids) {
9711
- const { results } = await promisePool.PromisePool.for(ids).withConcurrency(this.client.parallelism).process(async (id) => {
9797
+ const { results, errors } = await promisePool.PromisePool.for(ids).withConcurrency(this.client.parallelism).handleError(async (error, id) => {
9798
+ console.warn(`Failed to get resource ${id}:`, error.message);
9799
+ return {
9800
+ id,
9801
+ _error: error.message,
9802
+ _decryptionFailed: error.message.includes("Cipher job failed") || error.message.includes("OperationError")
9803
+ };
9804
+ }).process(async (id) => {
9712
9805
  this.emit("id", id);
9713
- const data = await this.get(id);
9714
- this.emit("data", data);
9715
- return data;
9806
+ try {
9807
+ const data = await this.get(id);
9808
+ this.emit("data", data);
9809
+ return data;
9810
+ } catch (error) {
9811
+ if (error.message.includes("Cipher job failed") || error.message.includes("OperationError")) {
9812
+ console.warn(`Decryption failed for ${id}, returning basic info`);
9813
+ return {
9814
+ id,
9815
+ _decryptionFailed: true,
9816
+ _error: error.message
9817
+ };
9818
+ }
9819
+ throw error;
9820
+ }
9716
9821
  });
9717
9822
  this.emit("getMany", ids.length);
9718
9823
  return results;
@@ -9727,9 +9832,28 @@ class Resource extends EventEmitter {
9727
9832
  async getAll() {
9728
9833
  let ids = await this.listIds();
9729
9834
  if (ids.length === 0) return [];
9730
- const { results } = await promisePool.PromisePool.for(ids).withConcurrency(this.client.parallelism).process(async (id) => {
9731
- const data = await this.get(id);
9732
- return data;
9835
+ const { results, errors } = await promisePool.PromisePool.for(ids).withConcurrency(this.client.parallelism).handleError(async (error, id) => {
9836
+ console.warn(`Failed to get resource ${id}:`, error.message);
9837
+ return {
9838
+ id,
9839
+ _error: error.message,
9840
+ _decryptionFailed: error.message.includes("Cipher job failed") || error.message.includes("OperationError")
9841
+ };
9842
+ }).process(async (id) => {
9843
+ try {
9844
+ const data = await this.get(id);
9845
+ return data;
9846
+ } catch (error) {
9847
+ if (error.message.includes("Cipher job failed") || error.message.includes("OperationError")) {
9848
+ console.warn(`Decryption failed for ${id}, returning basic info`);
9849
+ return {
9850
+ id,
9851
+ _decryptionFailed: true,
9852
+ _error: error.message
9853
+ };
9854
+ }
9855
+ throw error;
9856
+ }
9733
9857
  });
9734
9858
  this.emit("getAll", results.length);
9735
9859
  return results;
@@ -9944,7 +10068,27 @@ class Resource extends EventEmitter {
9944
10068
  * @returns {Object} Schema object for the version
9945
10069
  */
9946
10070
  async getSchemaForVersion(version) {
9947
- return this.schema;
10071
+ if (version === this.version) {
10072
+ return this.schema;
10073
+ }
10074
+ try {
10075
+ const compatibleSchema = new Schema({
10076
+ name: this.name,
10077
+ attributes: this.attributes,
10078
+ passphrase: this.passphrase,
10079
+ version,
10080
+ options: {
10081
+ ...this.options,
10082
+ // For older versions, be more lenient with decryption
10083
+ autoDecrypt: true,
10084
+ autoEncrypt: true
10085
+ }
10086
+ });
10087
+ return compatibleSchema;
10088
+ } catch (error) {
10089
+ console.warn(`Failed to create compatible schema for version ${version}, using current schema:`, error.message);
10090
+ return this.schema;
10091
+ }
9948
10092
  }
9949
10093
  /**
9950
10094
  * Create partition references after insert
@@ -10188,7 +10332,7 @@ class Database extends EventEmitter {
10188
10332
  this.version = "1";
10189
10333
  this.s3dbVersion = (() => {
10190
10334
  try {
10191
- return true ? "4.1.7" : "latest";
10335
+ return true ? "4.1.9" : "latest";
10192
10336
  } catch (e) {
10193
10337
  return "latest";
10194
10338
  }