55 PutObjectCommandOutput ,
66 S3Client ,
77 NotFound ,
8- ListObjectsV2Command ,
8+ paginateListObjectsV2 ,
9+ HeadObjectCommand ,
910} from '@aws-sdk/client-s3' ;
1011import { Parameters } from '@/src/utils/constants' ;
1112import { getAccountId } from './sts-utils' ;
@@ -34,20 +35,33 @@ export async function writeJsonToFile(
3435 ) ;
3536}
3637
38+ async function listItemObjectsWithPaginator ( bucket : string ) {
39+ const itemObjects = [ ] ;
40+ const paginatedItemObjects = paginateListObjectsV2 (
41+ {
42+ client : s3Client ,
43+ pageSize : 1000 ,
44+ } ,
45+ { Bucket : bucket }
46+ ) ;
47+
48+ for await ( const page of paginatedItemObjects ) {
49+ if ( page . Contents ) {
50+ itemObjects . push ( ...page . Contents . map ( ( item ) => item . Key ) ) ;
51+ }
52+ }
53+
54+ return itemObjects . length > 0 ? itemObjects : [ ] ;
55+ }
56+
3757export async function getItemObjects (
3858 templateId : string
3959) : Promise < unknown | void > {
4060 try {
41- const items = await s3Client . send (
42- new ListObjectsV2Command ( {
43- Bucket : sourceBucket ,
44- } )
45- ) ;
61+ const items = await listItemObjectsWithPaginator ( sourceBucket as string ) ;
4662
47- if ( items . Contents && items . Contents . length > 0 ) {
48- const itemObjects = items . Contents ?. filter ( ( item ) =>
49- item [ 'Key' ] ?. includes ( templateId )
50- ) ;
63+ if ( items . length > 0 ) {
64+ const itemObjects = items . filter ( ( item ) => item . includes ( templateId ) ) ;
5165 return itemObjects ;
5266 } else {
5367 throw Error ;
@@ -64,25 +78,35 @@ export async function getItemObjects(
6478export async function copyObjects (
6579 owner : string ,
6680 sourceKey : string ,
67- templateId : string ,
68- versionId : string ,
6981 clientId : string
7082) {
7183 const destinationKey = sourceKey . replace ( owner , clientId ) ;
72- console . log ( { sourceKey, destinationKey } ) ;
84+
85+ // Get existing metadata
86+ const head = await s3Client . send (
87+ new HeadObjectCommand ( {
88+ Bucket : sourceBucket ,
89+ Key : sourceKey ,
90+ } )
91+ ) ;
92+
93+ const existingMetadata = head . Metadata || { } ;
94+
95+ // 2. Update just the one key necessary
96+ const { [ 'owner' ] : _ , ...rest } = existingMetadata ;
97+ const updatedMetadata = {
98+ ...rest ,
99+ [ 'client-id' ] : clientId ,
100+ } ;
73101 return await s3Client . send (
74102 new CopyObjectCommand ( {
75103 CopySource : `${ sourceBucket } /${ sourceKey } ` ,
76104 Bucket : sourceBucket ,
77105 Key : destinationKey ,
78- Metadata : {
79- 'client-id' : clientId ,
80- 'file-type' : 'pdf-template' ,
81- 'template-id' : templateId ,
82- 'version-id' : versionId ,
83- } ,
106+ Metadata : updatedMetadata ,
84107 MetadataDirective : 'REPLACE' ,
85108 TaggingDirective : 'COPY' ,
109+ ContentType : head . ContentType ,
86110 } )
87111 ) ;
88112}
@@ -102,24 +126,16 @@ export async function backupObject(parameters: Parameters) {
102126 const bucketName = `nhs-notify-${ accountId } -eu-west-2-main-acct-migration-backup` ;
103127 const key = `ownership-transfer/templates/s3-objects/${ environment } /` ;
104128
105- const items = await s3Client . send (
106- new ListObjectsV2Command ( {
107- Bucket : sourceBucket ,
108- } )
109- ) ;
110-
111- if ( items [ 'Contents' ] && items [ 'Contents' ] . length <= 0 ) {
112- return ;
113- }
129+ const items = await listItemObjectsWithPaginator ( sourceBucket as string ) ;
114130
115- console . log ( `Found ${ items [ 'Contents' ] ? .length } objects in S3` ) ;
131+ console . log ( `Found ${ items . length } objects in S3` ) ;
116132
117- for ( const item of items [ 'Contents' ] ) {
133+ for ( const item of items ) {
118134 await s3Client . send (
119135 new CopyObjectCommand ( {
120136 Bucket : bucketName ,
121- Key : key + item . Key ,
122- CopySource : `${ sourceBucket } /${ item . Key } ` ,
137+ Key : key + item ,
138+ CopySource : `${ sourceBucket } /${ item } ` ,
123139 MetadataDirective : 'COPY' ,
124140 } )
125141 ) ;
0 commit comments