Skip to content

Commit ebaa06d

Browse files
committed
address comments
1 parent 5ec8e7f commit ebaa06d

File tree

11 files changed

+90
-114
lines changed

11 files changed

+90
-114
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"@opentelemetry/sdk-trace-base": "2.0.1",
7272
"@opentelemetry/sdk-trace-node": "2.0.1",
7373
"@tree-sitter-grammars/tree-sitter-yaml": "0.7.1",
74-
"archiver": "^7.0.1",
74+
"archiver": "7.0.1",
7575
"axios": "1.11.0",
7676
"deep-object-diff": "1.1.9",
7777
"fast-deep-equal": "3.1.3",

src/artifactexporter/ArtifactExporter.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ export class ArtifactExporter {
4444

4545
constructor(
4646
private readonly s3Service: S3Service,
47-
private readonly bucketName: string,
48-
private readonly s3KeyPrefix: string = '',
4947
private readonly document?: Document,
5048
private readonly templateAbsPath?: string,
5149
) {
@@ -100,7 +98,7 @@ export class ArtifactExporter {
10098

10199
const properties = resource.Properties as Record<string, unknown> | undefined;
102100
if (properties) {
103-
const exporter = new ExporterClass(this.s3Service, this.bucketName, this.s3KeyPrefix);
101+
const exporter = new ExporterClass(this.s3Service);
104102
const propertyName = exporter.propertyName;
105103
const localFilePath = properties[propertyName];
106104

@@ -157,7 +155,7 @@ export class ArtifactExporter {
157155
return result;
158156
}
159157

160-
async export(): Promise<unknown> {
158+
async export(bucketName: string, s3KeyPrefix: string = ''): Promise<unknown> {
161159
if (
162160
this.templateDict === undefined ||
163161
this.templateDict === null ||
@@ -167,13 +165,13 @@ export class ArtifactExporter {
167165
return this.templateDict;
168166
}
169167

170-
await this.exportResources();
168+
await this.exportResources(bucketName, s3KeyPrefix);
171169
return this.templateType === DocumentType.YAML
172170
? this.convertIntrinsicFunctionKeys(this.templateDict)
173171
: this.templateDict;
174172
}
175173

176-
private async exportResources(): Promise<void> {
174+
private async exportResources(bucketName: string, s3KeyPrefix: string): Promise<void> {
177175
const artifactMap = this.getResourceMapWithArtifact();
178176

179177
for (const [resourceType, artifacts] of Object.entries(artifactMap)) {
@@ -190,14 +188,14 @@ export class ArtifactExporter {
190188
continue;
191189
}
192190

193-
const exporter = new ExporterClass(this.s3Service, this.bucketName, this.s3KeyPrefix);
191+
const exporter = new ExporterClass(this.s3Service);
194192
const templateUri = this.templateUri;
195193
const templatePath = templateUri.startsWith('file:') ? fileURLToPath(templateUri) : templateUri;
196194
const templateDir = dirname(templatePath);
197195
const artifactAbsPath = isAbsolute(artifact.localFilePath)
198196
? artifact.localFilePath
199197
: resolve(templateDir, artifact.localFilePath);
200-
await exporter.export(artifact.resourcePropertyDict, artifactAbsPath);
198+
await exporter.export(artifact.resourcePropertyDict, artifactAbsPath, bucketName, s3KeyPrefix);
201199
}
202200
}
203201
}

src/artifactexporter/ResourceExporters.ts

Lines changed: 61 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
420404
export const RESOURCE_EXPORTER_MAP = new Map([
421405
['AWS::Serverless::Function', ServerlessFunctionResource],
422406
['AWS::Serverless::Api', ServerlessApiResource],

src/document/Document.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class Document {
4444
if (this.documentType === DocumentType.JSON) {
4545
return parseJson(this.contents());
4646
}
47-
return parseYaml(this.contents(), 0, false);
47+
return parseYaml(this.contents(), 0, true);
4848
}
4949

5050
public getLine(lineNumber: number): string | undefined {

0 commit comments

Comments
 (0)