diff --git a/src/lib/s3.ts b/src/lib/s3.ts index 6e11aa1..1b4c5b6 100644 --- a/src/lib/s3.ts +++ b/src/lib/s3.ts @@ -164,21 +164,48 @@ export interface BundleHistory { history: BundleEvent[]; } +/** + * Lists every object key under `prefix` (ListObjectsV2: up to 1000 keys per page, uses continuation). + */ +export async function listAllObjectKeysForPrefix( + s3: Pick, + bucket: string, + prefix: string, +): Promise { + const keys: string[] = []; + let continuationToken: string | undefined; + + for (;;) { + const listResponse = await s3.send( + new ListObjectsV2Command({ + Bucket: bucket, + Prefix: prefix, + ContinuationToken: continuationToken, + }), + ); + + for (const obj of listResponse.Contents ?? []) { + if (obj.Key) { + keys.push(obj.Key); + } + } + + if (!listResponse.IsTruncated || !listResponse.NextContinuationToken) { + break; + } + continuationToken = listResponse.NextContinuationToken; + } + + return keys; +} + export async function getBundleHistory( bundleKey: string, ): Promise { const prefix = `bundles/${bundleKey}/`; - const listCommand = new ListObjectsV2Command({ - Bucket: BUCKET_NAME, - Prefix: prefix, - }); - - const listResponse = await s3Client.send(listCommand); - const keys = listResponse.Contents?.map((obj) => obj.Key).filter( - Boolean, - ) as string[]; + const keys = await listAllObjectKeysForPrefix(s3Client, BUCKET_NAME, prefix); - if (!keys || keys.length === 0) { + if (keys.length === 0) { return null; }