s3db.js 4.1.7 → 4.1.8
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 +83 -16
- package/dist/s3db.cjs.js +82 -42
- package/dist/s3db.cjs.min.js +5 -5
- package/dist/s3db.es.js +82 -42
- package/dist/s3db.es.min.js +1 -1
- package/dist/s3db.iife.js +82 -42
- package/dist/s3db.iife.min.js +6 -6
- package/package.json +1 -1
package/dist/s3db.es.js
CHANGED
|
@@ -9234,36 +9234,45 @@ class Resource extends EventEmitter {
|
|
|
9234
9234
|
*/
|
|
9235
9235
|
async get(id) {
|
|
9236
9236
|
const key = this.getResourceKey(id);
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9237
|
+
try {
|
|
9238
|
+
const request = await this.client.headObject(key);
|
|
9239
|
+
const objectVersion = this.extractVersionFromKey(key) || this.version;
|
|
9240
|
+
const schema = await this.getSchemaForVersion(objectVersion);
|
|
9241
|
+
let metadata = await schema.unmapper(request.Metadata);
|
|
9242
|
+
const behaviorImpl = getBehavior(this.behavior);
|
|
9243
|
+
let body = "";
|
|
9244
|
+
if (request.ContentLength > 0) {
|
|
9245
|
+
try {
|
|
9246
|
+
const fullObject = await this.client.getObject(key);
|
|
9247
|
+
body = await streamToString(fullObject.Body);
|
|
9248
|
+
} catch (error) {
|
|
9249
|
+
console.warn(`Failed to read body for resource ${id}:`, error.message);
|
|
9250
|
+
body = "";
|
|
9251
|
+
}
|
|
9249
9252
|
}
|
|
9253
|
+
const { metadata: processedMetadata } = await behaviorImpl.handleGet({
|
|
9254
|
+
resource: this,
|
|
9255
|
+
metadata,
|
|
9256
|
+
body
|
|
9257
|
+
});
|
|
9258
|
+
let data = processedMetadata;
|
|
9259
|
+
data.id = id;
|
|
9260
|
+
data._contentLength = request.ContentLength;
|
|
9261
|
+
data._lastModified = request.LastModified;
|
|
9262
|
+
data._hasContent = request.ContentLength > 0;
|
|
9263
|
+
data._mimeType = request.ContentType || null;
|
|
9264
|
+
if (request.VersionId) data._versionId = request.VersionId;
|
|
9265
|
+
if (request.Expiration) data._expiresAt = request.Expiration;
|
|
9266
|
+
data._definitionHash = this.getDefinitionHash();
|
|
9267
|
+
this.emit("get", data);
|
|
9268
|
+
return data;
|
|
9269
|
+
} catch (error) {
|
|
9270
|
+
const enhancedError = new Error(`Failed to get resource with id '${id}': ${error.message}`);
|
|
9271
|
+
enhancedError.originalError = error;
|
|
9272
|
+
enhancedError.resourceId = id;
|
|
9273
|
+
enhancedError.resourceKey = key;
|
|
9274
|
+
throw enhancedError;
|
|
9250
9275
|
}
|
|
9251
|
-
const { metadata: processedMetadata } = await behaviorImpl.handleGet({
|
|
9252
|
-
resource: this,
|
|
9253
|
-
metadata,
|
|
9254
|
-
body
|
|
9255
|
-
});
|
|
9256
|
-
let data = processedMetadata;
|
|
9257
|
-
data.id = id;
|
|
9258
|
-
data._contentLength = request.ContentLength;
|
|
9259
|
-
data._lastModified = request.LastModified;
|
|
9260
|
-
data._hasContent = request.ContentLength > 0;
|
|
9261
|
-
data._mimeType = request.ContentType || null;
|
|
9262
|
-
if (request.VersionId) data._versionId = request.VersionId;
|
|
9263
|
-
if (request.Expiration) data._expiresAt = request.Expiration;
|
|
9264
|
-
data._definitionHash = this.getDefinitionHash();
|
|
9265
|
-
this.emit("get", data);
|
|
9266
|
-
return data;
|
|
9267
9276
|
}
|
|
9268
9277
|
/**
|
|
9269
9278
|
* Check if a resource exists by ID
|
|
@@ -9545,15 +9554,21 @@ class Resource extends EventEmitter {
|
|
|
9545
9554
|
return { deletedCount, resource: this.name };
|
|
9546
9555
|
}
|
|
9547
9556
|
/**
|
|
9548
|
-
* List resource IDs with optional partition filtering
|
|
9557
|
+
* List resource IDs with optional partition filtering and pagination
|
|
9549
9558
|
* @param {Object} [params] - List parameters
|
|
9550
9559
|
* @param {string} [params.partition] - Partition name to list from
|
|
9551
9560
|
* @param {Object} [params.partitionValues] - Partition field values to filter by
|
|
9561
|
+
* @param {number} [params.limit] - Maximum number of results to return
|
|
9562
|
+
* @param {number} [params.offset=0] - Offset for pagination
|
|
9552
9563
|
* @returns {Promise<string[]>} Array of resource IDs (strings)
|
|
9553
9564
|
* @example
|
|
9554
9565
|
* // List all IDs
|
|
9555
9566
|
* const allIds = await resource.listIds();
|
|
9556
9567
|
*
|
|
9568
|
+
* // List IDs with pagination
|
|
9569
|
+
* const firstPageIds = await resource.listIds({ limit: 10, offset: 0 });
|
|
9570
|
+
* const secondPageIds = await resource.listIds({ limit: 10, offset: 10 });
|
|
9571
|
+
*
|
|
9557
9572
|
* // List IDs from specific partition
|
|
9558
9573
|
* const googleUserIds = await resource.listIds({
|
|
9559
9574
|
* partition: 'byUtmSource',
|
|
@@ -9566,7 +9581,7 @@ class Resource extends EventEmitter {
|
|
|
9566
9581
|
* partitionValues: { category: 'electronics', region: 'US' }
|
|
9567
9582
|
* });
|
|
9568
9583
|
*/
|
|
9569
|
-
async listIds({ partition = null, partitionValues = {} } = {}) {
|
|
9584
|
+
async listIds({ partition = null, partitionValues = {}, limit, offset = 0 } = {}) {
|
|
9570
9585
|
let prefix;
|
|
9571
9586
|
if (partition && Object.keys(partitionValues).length > 0) {
|
|
9572
9587
|
const partitionDef = this.options.partitions[partition];
|
|
@@ -9590,8 +9605,11 @@ class Resource extends EventEmitter {
|
|
|
9590
9605
|
} else {
|
|
9591
9606
|
prefix = `resource=${this.name}/v=${this.version}`;
|
|
9592
9607
|
}
|
|
9593
|
-
const keys = await this.client.
|
|
9594
|
-
prefix
|
|
9608
|
+
const keys = await this.client.getKeysPage({
|
|
9609
|
+
prefix,
|
|
9610
|
+
offset,
|
|
9611
|
+
amount: limit || 1e3
|
|
9612
|
+
// Default to 1000 if no limit specified
|
|
9595
9613
|
});
|
|
9596
9614
|
const ids = keys.map((key) => {
|
|
9597
9615
|
const parts = key.split("/");
|
|
@@ -9721,6 +9739,7 @@ class Resource extends EventEmitter {
|
|
|
9721
9739
|
* @param {number} [params.size=100] - Page size
|
|
9722
9740
|
* @param {string} [params.partition] - Partition name to page from
|
|
9723
9741
|
* @param {Object} [params.partitionValues] - Partition field values to filter by
|
|
9742
|
+
* @param {boolean} [params.skipCount=false] - Skip total count for performance (useful for large collections)
|
|
9724
9743
|
* @returns {Promise<Object>} Page result with items and pagination info
|
|
9725
9744
|
* @example
|
|
9726
9745
|
* // Get first page of all resources
|
|
@@ -9735,22 +9754,43 @@ class Resource extends EventEmitter {
|
|
|
9735
9754
|
* offset: 0,
|
|
9736
9755
|
* size: 5
|
|
9737
9756
|
* });
|
|
9757
|
+
*
|
|
9758
|
+
* // Skip count for performance in large collections
|
|
9759
|
+
* const fastPage = await resource.page({
|
|
9760
|
+
* offset: 0,
|
|
9761
|
+
* size: 100,
|
|
9762
|
+
* skipCount: true
|
|
9763
|
+
* });
|
|
9764
|
+
* console.log(`Got ${fastPage.items.length} items`); // totalItems will be null
|
|
9738
9765
|
*/
|
|
9739
|
-
async page({ offset = 0, size = 100, partition = null, partitionValues = {} } = {}) {
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9766
|
+
async page({ offset = 0, size = 100, partition = null, partitionValues = {}, skipCount = false } = {}) {
|
|
9767
|
+
let totalItems = null;
|
|
9768
|
+
let totalPages = null;
|
|
9769
|
+
if (!skipCount) {
|
|
9770
|
+
totalItems = await this.count({ partition, partitionValues });
|
|
9771
|
+
totalPages = Math.ceil(totalItems / size);
|
|
9772
|
+
}
|
|
9743
9773
|
const page = Math.floor(offset / size);
|
|
9744
|
-
const
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9774
|
+
const items = await this.list({
|
|
9775
|
+
partition,
|
|
9776
|
+
partitionValues,
|
|
9777
|
+
limit: size,
|
|
9778
|
+
offset
|
|
9779
|
+
});
|
|
9748
9780
|
const result = {
|
|
9749
9781
|
items,
|
|
9750
9782
|
totalItems,
|
|
9751
9783
|
page,
|
|
9752
9784
|
pageSize: size,
|
|
9753
|
-
totalPages
|
|
9785
|
+
totalPages,
|
|
9786
|
+
// Add additional metadata for debugging
|
|
9787
|
+
_debug: {
|
|
9788
|
+
requestedSize: size,
|
|
9789
|
+
requestedOffset: offset,
|
|
9790
|
+
actualItemsReturned: items.length,
|
|
9791
|
+
skipCount,
|
|
9792
|
+
hasTotalItems: totalItems !== null
|
|
9793
|
+
}
|
|
9754
9794
|
};
|
|
9755
9795
|
this.emit("page", result);
|
|
9756
9796
|
return result;
|
|
@@ -10146,7 +10186,7 @@ class Database extends EventEmitter {
|
|
|
10146
10186
|
this.version = "1";
|
|
10147
10187
|
this.s3dbVersion = (() => {
|
|
10148
10188
|
try {
|
|
10149
|
-
return true ? "4.1.
|
|
10189
|
+
return true ? "4.1.7" : "latest";
|
|
10150
10190
|
} catch (e) {
|
|
10151
10191
|
return "latest";
|
|
10152
10192
|
}
|