1- import {
2- existsSync ,
3- mkdtempSync ,
4- copyFileSync ,
5- rmSync ,
6- createWriteStream ,
7- statSync ,
8- openSync ,
9- readSync ,
10- closeSync ,
11- } from 'fs' ;
1+ import { existsSync , mkdtempSync , copyFileSync , rmSync , createWriteStream , statSync , readFileSync } from 'fs' ;
122import { tmpdir } from 'os' ;
133import path , { join , basename } from 'path' ;
4+ import { pathToFileURL } from 'url' ;
145import archiver from 'archiver' ;
156import { dump } from 'js-yaml' ;
7+ import { detectDocumentType } from '../document/DocumentUtils' ;
168import { S3Service } from '../services/S3Service' ;
179import { ArtifactExporter } from './ArtifactExporter' ;
1810
1911export function isS3Url ( url : string ) : boolean {
20- return typeof url === 'string' && / ^ s 3 : \/ \/ [ ^ / ] + \/ .+ / . test ( url ) ;
12+ return / ^ s 3 : \/ \/ [ ^ / ] + \/ .+ / . test ( url ) ;
2113}
2214
2315export function isLocalFile ( filePath : string ) : boolean {
@@ -31,26 +23,9 @@ function isLocalFolder(path: string): boolean {
3123function isArchiveFile ( filePath : string ) {
3224 // Quick extension check
3325 const ext = path . extname ( filePath ) . toLowerCase ( ) ;
34- const archiveExts = [ '.zip' , '.rar' , '.7z' , '.tar' , '.gz' , '.tgz' ] ;
35-
36- if ( ! archiveExts . includes ( ext ) ) return false ;
37-
38- // Verify with magic numbers
39- try {
40- const fd = openSync ( filePath , 'r' ) ;
41- const buffer = Buffer . alloc ( 8 ) ;
42- readSync ( fd , buffer , 0 , 8 , 0 ) ;
43- closeSync ( fd ) ;
44-
45- return (
46- ( buffer [ 0 ] === 0x50 && buffer [ 1 ] === 0x4b ) || // ZIP
47- buffer . toString ( 'ascii' , 0 , 4 ) === 'Rar!' || // RAR
48- ( buffer [ 0 ] === 0x37 && buffer [ 1 ] === 0x7a ) || // 7Z
49- ( buffer [ 0 ] === 0x1f && buffer [ 1 ] === 0x8b ) // GZIP
50- ) ;
51- } catch {
52- return false ;
53- }
26+ const archiveExts = [ '.zip' , '.rar' , '.7z' , '.tar' , '.gz' , '.tgz' , '.zst' , '.war' ] ;
27+
28+ return archiveExts . includes ( ext ) ;
5429}
5530
5631function copyToTempDir ( filePath : string ) : string {
@@ -228,25 +203,25 @@ export abstract class ResourceWithS3UrlDict extends Resource {
228203 }
229204}
230205
231- export class ServerlessFunctionResource extends Resource {
206+ class ServerlessFunctionResource extends Resource {
232207 public override resourceType = 'AWS::Serverless::Function' ;
233208 public override propertyName = 'CodeUri' ;
234209 protected override forceZip = true ;
235210}
236211
237- export class ServerlessApiResource extends Resource {
212+ class ServerlessApiResource extends Resource {
238213 public override resourceType = 'AWS::Serverless::Api' ;
239214 public override propertyName = 'DefinitionUri' ;
240215 protected override packageNullProperty = false ;
241216}
242217
243- export class GraphQLSchemaResource extends Resource {
218+ class GraphQLSchemaResource extends Resource {
244219 public override resourceType = 'AWS::AppSync::GraphQLSchema' ;
245220 public override propertyName = 'DefinitionS3Location' ;
246221 protected override packageNullProperty = false ;
247222}
248223
249- export class LambdaFunctionResource extends ResourceWithS3UrlDict {
224+ class LambdaFunctionResource extends ResourceWithS3UrlDict {
250225 public override resourceType = 'AWS::Lambda::Function' ;
251226 public override propertyName = 'Code' ;
252227 protected override bucketNameProperty = 'S3Bucket' ;
@@ -255,7 +230,7 @@ export class LambdaFunctionResource extends ResourceWithS3UrlDict {
255230 protected override forceZip = true ;
256231}
257232
258- export class ApiGatewayRestApiResource extends ResourceWithS3UrlDict {
233+ class ApiGatewayRestApiResource extends ResourceWithS3UrlDict {
259234 public override resourceType = 'AWS::ApiGateway::RestApi' ;
260235 public override propertyName = 'BodyS3Location' ;
261236 protected override packageNullProperty = false ;
@@ -264,7 +239,7 @@ export class ApiGatewayRestApiResource extends ResourceWithS3UrlDict {
264239 protected override versionProperty = 'Version' ;
265240}
266241
267- export class CloudFormationStackResource extends Resource {
242+ class CloudFormationStackResource extends Resource {
268243 public override resourceType = 'AWS::CloudFormation::Stack' ;
269244 public override propertyName = 'TemplateURL' ;
270245
@@ -278,7 +253,11 @@ export class CloudFormationStackResource extends Resource {
278253 throw new Error ( `Invalid template path: ${ templateAbsPath } ` ) ;
279254 }
280255
281- const template = new ArtifactExporter ( this . s3Service , undefined , templateAbsPath ) ;
256+ const templateUri = pathToFileURL ( templateAbsPath ) . href ;
257+ const content = readFileSync ( templateAbsPath , 'utf8' ) ;
258+ const templateType = detectDocumentType ( templateUri , content ) . type ;
259+
260+ const template = new ArtifactExporter ( this . s3Service , templateType , templateUri , content ) ;
282261 const exportedTemplateDict = await template . export ( bucketName , s3KeyPrefix ) ;
283262 const exportedTemplateStr = dump ( exportedTemplateDict ) ;
284263
0 commit comments