@@ -80,8 +80,7 @@ function getS3Key(keyPrefix: string, filePath: string): string {
8080 const filename = basename ( filePath ) ;
8181 const timestamp = Date . now ( ) ;
8282 const parts = filename . split ( '.' ) ;
83- const normalizedPrefix = keyPrefix ? keyPrefix . replace ( / \/ + $ / , '' ) : '' ;
84- const prefix = normalizedPrefix ? `${ normalizedPrefix } /artifact` : 'artifact' ;
83+ const prefix = keyPrefix ? `${ keyPrefix } /artifact` : 'artifact' ;
8584
8685 if ( parts . length > 1 ) {
8786 const nameWithoutExt = parts . slice ( 0 , - 1 ) . join ( '.' ) ;
@@ -97,61 +96,60 @@ export abstract class Resource {
9796 public abstract propertyName : string ;
9897 protected packageNullProperty = true ;
9998 protected forceZip = false ;
100- protected bucketName : string ;
101- protected s3KeyPrefix : string ;
10299
103- constructor (
104- protected s3Service : S3Service ,
105- bucketName : string ,
106- s3KeyPrefix : string = '' ,
107- ) {
108- this . bucketName = bucketName ;
109- this . s3KeyPrefix = s3KeyPrefix ;
110- }
100+ constructor ( protected s3Service : S3Service ) { }
111101
112- async export ( resourcePropertyDict : Record < string , unknown > , artifactAbsPath : string ) : Promise < void > {
102+ async export (
103+ resourcePropertyDict : Record < string , unknown > ,
104+ artifactAbsPath : string ,
105+ bucketName : string ,
106+ s3KeyPrefix : string ,
107+ ) : Promise < void > {
113108 if ( ! resourcePropertyDict ) {
114109 return ;
115110 }
116111
117- const property = resourcePropertyDict ;
118- if ( ! property ) {
112+ if ( ! resourcePropertyDict ) {
119113 return ;
120114 }
121115
122- const propertyValue = property [ this . propertyName ] ;
116+ const propertyValue = resourcePropertyDict [ this . propertyName ] ;
123117
124118 if ( ! propertyValue && ! this . packageNullProperty ) {
125119 return ;
126120 }
127121
128- if ( typeof propertyValue === 'object' && propertyValue !== undefined ) {
122+ if ( typeof propertyValue === 'object' ) {
129123 return ;
130124 }
131125
132126 let tempDir : string | undefined = undefined ;
133127 if ( isLocalFile ( artifactAbsPath ) && ! isArchiveFile ( artifactAbsPath ) && this . forceZip ) {
134128 tempDir = copyToTempDir ( artifactAbsPath ) ;
135- property [ this . propertyName ] = tempDir ;
129+ resourcePropertyDict [ this . propertyName ] = tempDir ;
136130 }
137131
138132 try {
139133 const pathToUse = tempDir ?? artifactAbsPath ;
140- await this . doExport ( resourcePropertyDict , pathToUse ) ;
134+ await this . doExport ( resourcePropertyDict , pathToUse , bucketName , s3KeyPrefix ) ;
141135 } finally {
142136 if ( tempDir && existsSync ( tempDir ) ) {
143137 rmSync ( tempDir , { recursive : true } ) ;
144138 }
145139 }
146140 }
147141
148- async doExport ( resourcePropertyDict : Record < string , unknown > , artifactAbsPath : string ) : Promise < void > {
149- const property = resourcePropertyDict ;
150- if ( ! property ) {
142+ async doExport (
143+ resourcePropertyDict : Record < string , unknown > ,
144+ artifactAbsPath : string ,
145+ bucketName : string ,
146+ s3KeyPrefix : string ,
147+ ) : Promise < void > {
148+ if ( ! resourcePropertyDict ) {
151149 return ;
152150 }
153151
154- const localPath = property [ this . propertyName ] ;
152+ const localPath = resourcePropertyDict [ this . propertyName ] ;
155153
156154 if ( typeof localPath !== 'string' || isS3Url ( localPath ) ) {
157155 return ;
@@ -167,12 +165,13 @@ export abstract class Resource {
167165 }
168166
169167 try {
170- const key = getS3Key ( this . s3KeyPrefix , uploadPath ) ;
171- const s3Url = `s3://${ this . bucketName } /${ key } ` ;
168+ const key = getS3Key ( s3KeyPrefix , uploadPath ) ;
169+ const s3Url = `s3://${ bucketName } /${ key } ` ;
172170
173171 await this . s3Service . putObject ( uploadPath , s3Url ) ;
174172
175- property [ this . propertyName ] = s3Url ;
173+ // eslint-disable-next-line require-atomic-updates
174+ resourcePropertyDict [ this . propertyName ] = s3Url ;
176175 } finally {
177176 if ( tempZipFile && existsSync ( tempZipFile ) ) {
178177 rmSync ( tempZipFile ) ;
@@ -186,13 +185,17 @@ export abstract class ResourceWithS3UrlDict extends Resource {
186185 protected abstract objectKeyProperty : string ;
187186 protected versionProperty ?: string ;
188187
189- override async doExport ( resourcePropertyDict : Record < string , unknown > , artifactAbsPath : string ) : Promise < void > {
190- const property = resourcePropertyDict ;
191- if ( ! property ) {
188+ override async doExport (
189+ resourcePropertyDict : Record < string , unknown > ,
190+ artifactAbsPath : string ,
191+ bucketName : string ,
192+ s3KeyPrefix : string ,
193+ ) : Promise < void > {
194+ if ( ! resourcePropertyDict ) {
192195 return ;
193196 }
194197
195- const localPath = property [ this . propertyName ] ;
198+ const localPath = resourcePropertyDict [ this . propertyName ] ;
196199
197200 if ( typeof localPath !== 'string' || isS3Url ( localPath ) ) {
198201 return ;
@@ -208,18 +211,19 @@ export abstract class ResourceWithS3UrlDict extends Resource {
208211 }
209212
210213 try {
211- const key = getS3Key ( this . s3KeyPrefix , uploadPath ) ;
212- const s3Url = `s3://${ this . bucketName } /${ key } ` ;
214+ const key = getS3Key ( s3KeyPrefix , uploadPath ) ;
215+ const s3Url = `s3://${ bucketName } /${ key } ` ;
213216
214217 const result = await this . s3Service . putObject ( uploadPath , s3Url ) ;
215218
216219 const s3Record : Record < string , string > = { } ;
217- s3Record [ this . bucketNameProperty ] = this . bucketName ;
220+ s3Record [ this . bucketNameProperty ] = bucketName ;
218221 s3Record [ this . objectKeyProperty ] = key ;
219222 if ( result . VersionId && this . versionProperty ) {
220223 s3Record [ this . versionProperty ] = result . VersionId ;
221224 }
222- property [ this . propertyName ] = s3Record ;
225+ // eslint-disable-next-line require-atomic-updates
226+ resourcePropertyDict [ this . propertyName ] = s3Record ;
223227 } finally {
224228 if ( tempZipFile && existsSync ( tempZipFile ) ) {
225229 rmSync ( tempZipFile ) ;
@@ -268,72 +272,71 @@ export class CloudFormationStackResource extends Resource {
268272 public override resourceType = 'AWS::CloudFormation::Stack' ;
269273 public override propertyName = 'TemplateURL' ;
270274
271- override async doExport ( resourcePropertyDict : Record < string , unknown > , templateAbsPath : string ) : Promise < void > {
275+ override async doExport (
276+ resourcePropertyDict : Record < string , unknown > ,
277+ templateAbsPath : string ,
278+ bucketName : string ,
279+ s3KeyPrefix : string ,
280+ ) : Promise < void > {
272281 if ( ! isLocalFile ( templateAbsPath ) ) {
273282 throw new Error ( `Invalid template path: ${ templateAbsPath } ` ) ;
274283 }
275284
276- const template = new ArtifactExporter (
277- this . s3Service ,
278- this . bucketName ,
279- this . s3KeyPrefix ,
280- undefined ,
281- templateAbsPath ,
282- ) ;
283- const exportedTemplateDict = await template . export ( ) ;
285+ const template = new ArtifactExporter ( this . s3Service , undefined , templateAbsPath ) ;
286+ const exportedTemplateDict = await template . export ( bucketName , s3KeyPrefix ) ;
284287 const exportedTemplateStr = dump ( exportedTemplateDict ) ;
285288
286- const key = getS3Key ( this . s3KeyPrefix , templateAbsPath ) ;
287- await this . s3Service . putObjectContent ( exportedTemplateStr , this . bucketName , key ) ;
288- const s3Url = `s3://${ this . bucketName } /${ key } ` ;
289+ const key = getS3Key ( s3KeyPrefix , templateAbsPath ) ;
290+ await this . s3Service . putObjectContent ( exportedTemplateStr , bucketName , key ) ;
291+ const s3Url = `s3://${ bucketName } /${ key } ` ;
289292
290293 resourcePropertyDict [ this . propertyName ] = s3Url ;
291294 }
292295}
293296
294- export class ServerlessApplicationResource extends CloudFormationStackResource {
297+ class ServerlessApplicationResource extends CloudFormationStackResource {
295298 public override resourceType = 'AWS::Serverless::Application' ;
296299 public override propertyName = 'Location' ;
297300}
298301
299- export class AppSyncResolverRequestTemplateResource extends Resource {
302+ class AppSyncResolverRequestTemplateResource extends Resource {
300303 public override resourceType = 'AWS::AppSync::Resolver' ;
301304 public override propertyName = 'RequestMappingTemplateS3Location' ;
302305 protected override packageNullProperty = false ;
303306}
304307
305- export class AppSyncResolverResponseTemplateResource extends Resource {
308+ class AppSyncResolverResponseTemplateResource extends Resource {
306309 public override resourceType = 'AWS::AppSync::Resolver' ;
307310 public override propertyName = 'ResponseMappingTemplateS3Location' ;
308311 protected override packageNullProperty = false ;
309312}
310313
311- export class AppSyncFunctionConfigurationRequestTemplateResource extends Resource {
314+ class AppSyncFunctionConfigurationRequestTemplateResource extends Resource {
312315 public override resourceType = 'AWS::AppSync::FunctionConfiguration' ;
313316 public override propertyName = 'RequestMappingTemplateS3Location' ;
314317 protected override packageNullProperty = false ;
315318}
316319
317- export class AppSyncFunctionConfigurationResponseTemplateResource extends Resource {
320+ class AppSyncFunctionConfigurationResponseTemplateResource extends Resource {
318321 public override resourceType = 'AWS::AppSync::FunctionConfiguration' ;
319322 public override propertyName = 'ResponseMappingTemplateS3Location' ;
320323 protected override packageNullProperty = false ;
321324}
322325
323- export class ElasticBeanstalkApplicationVersion extends ResourceWithS3UrlDict {
326+ class ElasticBeanstalkApplicationVersion extends ResourceWithS3UrlDict {
324327 public override resourceType = 'AWS::ElasticBeanstalk::ApplicationVersion' ;
325328 public override propertyName = 'SourceBundle' ;
326329 protected override bucketNameProperty = 'S3Bucket' ;
327330 protected override objectKeyProperty = 'S3Key' ;
328331}
329332
330- export class ServerlessLayerVersionResource extends Resource {
333+ class ServerlessLayerVersionResource extends Resource {
331334 public override resourceType = 'AWS::Serverless::LayerVersion' ;
332335 public override propertyName = 'ContentUri' ;
333336 protected override forceZip = true ;
334337}
335338
336- export class LambdaLayerVersionResource extends ResourceWithS3UrlDict {
339+ class LambdaLayerVersionResource extends ResourceWithS3UrlDict {
337340 public override resourceType = 'AWS::Lambda::LayerVersion' ;
338341 public override propertyName = 'Content' ;
339342 protected override bucketNameProperty = 'S3Bucket' ;
@@ -342,12 +345,12 @@ export class LambdaLayerVersionResource extends ResourceWithS3UrlDict {
342345 protected override forceZip = true ;
343346}
344347
345- export class GlueJobCommandScriptLocationResource extends Resource {
348+ class GlueJobCommandScriptLocationResource extends Resource {
346349 public resourceType = 'AWS::Glue::Job' ;
347350 public propertyName = 'Command.ScriptLocation' ;
348351}
349352
350- export class StepFunctionsStateMachineDefinitionResource extends ResourceWithS3UrlDict {
353+ class StepFunctionsStateMachineDefinitionResource extends ResourceWithS3UrlDict {
351354 public override resourceType = 'AWS::StepFunctions::StateMachine' ;
352355 public override propertyName = 'DefinitionS3Location' ;
353356 protected override bucketNameProperty = 'Bucket' ;
@@ -356,7 +359,7 @@ export class StepFunctionsStateMachineDefinitionResource extends ResourceWithS3U
356359 protected override packageNullProperty = false ;
357360}
358361
359- export class ServerlessStateMachineDefinitionResource extends ResourceWithS3UrlDict {
362+ class ServerlessStateMachineDefinitionResource extends ResourceWithS3UrlDict {
360363 public override resourceType = 'AWS::Serverless::StateMachine' ;
361364 public override propertyName = 'DefinitionUri' ;
362365 protected override bucketNameProperty = 'Bucket' ;
@@ -365,7 +368,7 @@ export class ServerlessStateMachineDefinitionResource extends ResourceWithS3UrlD
365368 protected override packageNullProperty = false ;
366369}
367370
368- export class CodeCommitRepositoryS3Resource extends ResourceWithS3UrlDict {
371+ class CodeCommitRepositoryS3Resource extends ResourceWithS3UrlDict {
369372 public override resourceType = 'AWS::CodeCommit::Repository' ;
370373 public override propertyName = 'Code.S3' ;
371374 protected override bucketNameProperty = 'Bucket' ;
@@ -398,25 +401,6 @@ export const RESOURCES_EXPORT_LIST: Array<
398401 CodeCommitRepositoryS3Resource ,
399402] ;
400403
401- export const RESOURCES_WITH_ARTIFACT = new Set ( [
402- 'AWS::Serverless::Function' ,
403- 'AWS::Serverless::Api' ,
404- 'AWS::AppSync::GraphQLSchema' ,
405- 'AWS::AppSync::Resolver' ,
406- 'AWS::AppSync::FunctionConfiguration' ,
407- 'AWS::ApiGateway::RestApi' ,
408- 'AWS::Lambda::Function' ,
409- 'AWS::ElasticBeanstalk::ApplicationVersion' ,
410- 'AWS::CloudFormation::Stack' ,
411- 'AWS::Serverless::Application' ,
412- 'AWS::Serverless::LayerVersion' ,
413- 'AWS::Lambda::LayerVersion' ,
414- 'AWS::Glue::Job' ,
415- 'AWS::StepFunctions::StateMachine' ,
416- 'AWS::Serverless::StateMachine' ,
417- 'AWS::CodeCommit::Repository' ,
418- ] ) ;
419-
420404export const RESOURCE_EXPORTER_MAP = new Map ( [
421405 [ 'AWS::Serverless::Function' , ServerlessFunctionResource ] ,
422406 [ 'AWS::Serverless::Api' , ServerlessApiResource ] ,
0 commit comments