From 099b610b90fbe114b4a2bda6a07107268e3e1eec Mon Sep 17 00:00:00 2001 From: Yathi <511386+yuth@users.noreply.github.com> Date: Fri, 25 Sep 2020 19:05:56 -0700 Subject: [PATCH] fix(amplify-provider-awscloudformation): fix redudant upload message Update the s3 util accept a prameter which disables printing upload message. Updated appsync file upload utilt to print upload message only once. Migrated S3 class to typescript fix #5393 --- .eslintrc.js | 1 + .prettierignore | 1 + .../src/amplify-service-manager.js | 4 +- .../src/aws-utils/aws-cfn.js | 4 +- .../src/aws-utils/aws-s3.js | 218 ------------------ .../src/aws-utils/aws-s3.ts | 176 ++++++++++++++ .../src/aws-utils/paged-call.ts | 27 +++ .../src/delete-env.js | 4 +- .../src/initialize-env.js | 4 +- .../src/initializer.js | 6 +- .../src/push-resources.js | 8 +- .../src/upload-appsync-files.js | 17 +- .../tsconfig.json | 3 +- 13 files changed, 233 insertions(+), 240 deletions(-) delete mode 100644 packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.js create mode 100644 packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.ts create mode 100644 packages/amplify-provider-awscloudformation/src/aws-utils/paged-call.ts diff --git a/.eslintrc.js b/.eslintrc.js index 78e2265cb52..4dc6f4fbac6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -261,6 +261,7 @@ module.exports = { '/packages/graphql-transformer-*/lib', '/packages/amplify-headless-interface/lib', '/packages/amplify-util-headless-input/lib', + '/packages/amplify-provider-awscloudformation/lib', // Ignore CHANGELOG.md files '/packages/*/CHANGELOG.md' diff --git a/.prettierignore b/.prettierignore index 1d40c4d3a8d..27226ed62c3 100644 --- a/.prettierignore +++ b/.prettierignore @@ -8,3 +8,4 @@ packages/amplify-headless-interface/**/*.schema.json packages/*/CHANGELOG.md packages/amplify-cli-core/src/__tests__/testFiles +packages/amplify-provider-awscloudformation/lib/ \ No newline at end of file diff --git a/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js b/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js index 7c059831cee..2a14287c149 100644 --- a/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js +++ b/packages/amplify-provider-awscloudformation/src/amplify-service-manager.js @@ -2,7 +2,7 @@ const fs = require('fs-extra'); const path = require('path'); const inquirer = require('inquirer'); const sequential = require('promise-sequential'); -const S3 = require('./aws-utils/aws-s3'); +const { S3 } = require('./aws-utils/aws-s3'); const { getConfiguredAmplifyClient } = require('./aws-utils/aws-amplify'); const constants = require('./constants'); const { checkAmplifyServiceIAMPermission } = require('./amplify-service-permission-check'); @@ -396,7 +396,7 @@ async function searchAmplifyService(amplifyClient, stackName) { } function storeArtifactsForAmplifyService(context) { - return new S3(context).then(async s3 => { + return S3.getInstance(context).then(async s3 => { const currentCloudBackendDir = context.amplify.pathManager.getCurrentCloudBackendDirPath(); const amplifyMetaFilePath = path.join(currentCloudBackendDir, 'amplify-meta.json'); const backendConfigFilePath = path.join(currentCloudBackendDir, 'backend-config.json'); diff --git a/packages/amplify-provider-awscloudformation/src/aws-utils/aws-cfn.js b/packages/amplify-provider-awscloudformation/src/aws-utils/aws-cfn.js index 3d6a0ac62e6..ba79ec8f3ac 100644 --- a/packages/amplify-provider-awscloudformation/src/aws-utils/aws-cfn.js +++ b/packages/amplify-provider-awscloudformation/src/aws-utils/aws-cfn.js @@ -6,7 +6,7 @@ const chalk = require('chalk'); const columnify = require('columnify'); const aws = require('./aws.js'); -const S3 = require('./aws-s3'); +const { S3 } = require('./aws-s3'); const providerName = require('../constants').ProviderName; const { formUserAgentParam } = require('./user-agent'); const configurationManager = require('../configuration-manager'); @@ -207,7 +207,7 @@ class CloudFormation { throw new Error('Project deployment bucket has not been created yet. Use amplify init to initialize the project.'); } - return new S3(this.context) + return S3.getInstance(this.context) .then(s3 => { const s3Params = { Body: fs.createReadStream(filePath), diff --git a/packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.js b/packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.js deleted file mode 100644 index 82d36007761..00000000000 --- a/packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.js +++ /dev/null @@ -1,218 +0,0 @@ -const aws = require('./aws.js'); -const _ = require('lodash'); -const providerName = require('../constants').ProviderName; -const configurationManager = require('../configuration-manager'); -const fs = require('fs-extra'); -const ora = require('ora'); - -const minChunkSize = 5 * 1024 * 1024; // 5 MB https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3/ManagedUpload.html#minPartSize-property -class S3 { - constructor(context, options = {}) { - return (async () => { - let cred = {}; - try { - cred = await configurationManager.loadConfiguration(context); - } catch (e) { - // ignore missing config - } - this.context = context; - this.s3 = new aws.S3({ ...cred, ...options }); - return this; - })(); - } - - uploadFile(s3Params) { - // envName and bucket does not change during execution, cache them into a class level - // field. - if (this.uploadState === undefined) { - const projectDetails = this.context.amplify.getProjectDetails(); - const { envName } = this.context.amplify.getEnvInfo(); - const projectBucket = projectDetails.amplifyMeta.providers - ? projectDetails.amplifyMeta.providers[providerName].DeploymentBucketName - : projectDetails.teamProviderInfo[envName][providerName].DeploymentBucketName; - - this.uploadState = { - envName, - s3Params: { - Bucket: projectBucket, - }, - }; - } - - const augmentedS3Params = { - ...s3Params, - ...this.uploadState.s3Params, - }; - let uploadTask = null; - const spinner = new ora('Uploading Files...'); - spinner.start(); - if ( - (s3Params.Body instanceof fs.ReadStream && fs.statSync(s3Params.Body.path).size > minChunkSize) || - (Buffer.isBuffer(s3Params.Body) && s3Params.Body.length > minChunkSize) - ) { - uploadTask = this.s3.upload(augmentedS3Params); - uploadTask.on('httpUploadProgress', max => { - spinner.text = `Uploading Files...${Math.round((max.loaded / max.total) * 100)}%`; - }); - } else { - uploadTask = this.s3.putObject(augmentedS3Params); - } - - return uploadTask - .promise() - .catch(ex => { - spinner.stop(); - throw ex; - }) - .then(() => { - spinner.stop(); - return this.uploadState.s3Params.Bucket; - }); - } - - getFile(s3Params, envName = this.context.amplify.getEnvInfo().envName) { - const projectDetails = this.context.amplify.getProjectDetails(); - const projectBucket = projectDetails.teamProviderInfo[envName][providerName].DeploymentBucketName; - s3Params.Bucket = projectBucket; - - return this.s3 - .getObject(s3Params) - .promise() - .then(result => result.Body); - } - - createBucket(bucketName) { - // Check if bucket exists; - const params = { - Bucket: bucketName, - }; - - return this.ifBucketExists(bucketName).then(result => { - if (!result) { - this.context.print.warning( - 'The specified S3 bucket to store the CloudFormation templates is not present. We are creating one for you....', - ); - this.context.print.warning(`Bucket name: ${bucketName}`); - - return this.s3 - .createBucket(params) - .promise() - .then(() => this.s3.waitFor('bucketExists', params).promise()) - .then(() => { - this.context.print.success('S3 bucket successfully created'); - return bucketName; - }); - } - }); - } - - getAllObjectKeys(bucketName, continuationToken = null) { - return new Promise((resolve, reject) => { - this.s3 - .listObjectsV2({ Bucket: bucketName, ContinuationToken: continuationToken }) - .promise() - .then((result, lerr) => { - if (lerr) { - reject(lerr); - return; - } - const objects = result.Contents.map(r => { - return { Key: r.Key }; - }); - if (result.IsTruncated) { - this.getAllObjectKeys(bucketName, result.NextContinuationToken).then((result, error) => { - if (error) { - reject(error); - } else { - resolve(objects.concat(result)); - } - }); - } else { - resolve(objects); - } - }); - }); - } - - deleteAllObjects(bucketName) { - return new Promise((resolve, reject) => { - this.getAllObjectKeys(bucketName).then((bucketObjects, error) => { - if (error) reject(error); - const chunkedResult = _.chunk(bucketObjects, 1000); - - const deleteReq = chunkedResult - .map(res => { - return { - Bucket: bucketName, - Delete: { - Objects: res, - Quiet: false, - }, - }; - }) - .map(delParams => this.s3.deleteObjects(delParams)) - .map(delRequest => delRequest.promise()); - Promise.all(deleteReq) - .then(resolve) - .catch(reject); - }); - }); - } - - deleteS3Bucket(bucketName) { - return new Promise((resolve, reject) => { - this.ifBucketExists(bucketName).then((exists, err) => { - if (err) { - reject(err); - } - if (exists) { - this.deleteAllObjects(bucketName).then((result, err) => { - if (err) { - reject(err); - return; - } - this.s3 - .deleteBucket({ - Bucket: bucketName, - }) - .promise() - .then((dresult, derr) => { - if (derr) { - reject(derr); - return; - } - resolve(dresult); - }); - }); - } else { - resolve(); - } - }); - }); - } - - ifBucketExists(bucketName) { - return new Promise((resolve, reject) => { - this.s3.headBucket( - { - Bucket: bucketName, - }, - (err, data) => { - if (data !== null) { - resolve(true); - return; - } else { - if (err.statusCode === 404) { - resolve(false); - return; - } - } - - reject(err.message); - }, - ); - }); - } -} - -module.exports = S3; diff --git a/packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.ts b/packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.ts new file mode 100644 index 00000000000..83e44378198 --- /dev/null +++ b/packages/amplify-provider-awscloudformation/src/aws-utils/aws-s3.ts @@ -0,0 +1,176 @@ +import { $TSAny, $TSContext } from 'amplify-cli-core'; + +import aws from './aws.js'; +import _ from 'lodash'; +const providerName = require('../constants').ProviderName; +import configurationManager from '../configuration-manager'; +import fs from 'fs-extra'; +import ora from 'ora'; +import { pagedAWSCall } from './paged-call'; +import { ListObjectsV2Output, ListObjectsV2Request, NextToken } from 'aws-sdk/clients/s3'; + +const minChunkSize = 5 * 1024 * 1024; // 5 MB https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3/ManagedUpload.html#minPartSize-property + +export class S3 { + private static instance: S3; + private readonly context: $TSContext; + private readonly s3: AWS.S3; + private uploadState: { + envName: string; + s3Params: { + Bucket: string; + }; + }; + + static async getInstance(context: $TSContext, options = {}): Promise { + if (!S3.instance) { + let cred = {}; + try { + cred = await configurationManager.loadConfiguration(context); + } catch (e) { + // ignore missing config + } + + S3.instance = new S3(context, cred, options); + } + return S3.instance; + } + + private constructor(context, cred, options = {}) { + this.context = context; + this.s3 = new aws.S3({ ...cred, ...options }); + } + + private populateUploadState(): void { + const projectDetails = this.context.amplify.getProjectDetails(); + const { envName } = this.context.amplify.getEnvInfo(); + const projectBucket = projectDetails.amplifyMeta.providers + ? projectDetails.amplifyMeta.providers[providerName].DeploymentBucketName + : projectDetails.teamProviderInfo[envName][providerName].DeploymentBucketName; + + this.uploadState = { + envName, + s3Params: { + Bucket: projectBucket, + }, + }; + } + + async uploadFile(s3Params, showSpinner: boolean = true) { + // envName and bucket does not change during execution, cache them into a class level + // field. + if (this.uploadState === undefined) { + this.populateUploadState(); + } + let spinner = showSpinner ? ora('Uploading files...') : undefined; + + const augmentedS3Params = { + ...s3Params, + ...this.uploadState.s3Params, + }; + let uploadTask; + showSpinner && spinner.start('Uploading files...'); + if ( + (s3Params.Body instanceof fs.ReadStream && fs.statSync(s3Params.Body.path).size > minChunkSize) || + (Buffer.isBuffer(s3Params.Body) && s3Params.Body.length > minChunkSize) + ) { + uploadTask = this.s3.upload(augmentedS3Params); + uploadTask.on('httpUploadProgress', max => { + if (showSpinner) spinner.text = `Uploading Files...${Math.round((max.loaded / max.total) * 100)}%`; + }); + } else { + uploadTask = this.s3.putObject(augmentedS3Params); + } + + try { + await uploadTask.promise(); + showSpinner && spinner.stop(); + return this.uploadState.s3Params.Bucket; + } catch (ex) { + showSpinner && spinner.stop(); + throw ex; + } + } + + async getFile(s3Params, envName = this.context.amplify.getEnvInfo().envName) { + const projectDetails = this.context.amplify.getProjectDetails(); + const projectBucket = projectDetails.teamProviderInfo[envName][providerName].DeploymentBucketName; + s3Params.Bucket = projectBucket; + + const result = await this.s3.getObject(s3Params).promise(); + return result.Body; + } + + async createBucket(bucketName, throwIfExists: boolean = false): Promise { + // Check if bucket exists; + const params = { + Bucket: bucketName, + }; + + if (!(await this.ifBucketExists(bucketName))) { + this.context.print.warning( + 'The specified S3 bucket to store the CloudFormation templates is not present. We are creating one for you....', + ); + this.context.print.warning(`Bucket name: ${bucketName}`); + await this.s3.createBucket(params).promise(); + await this.s3.waitFor('bucketExists', params).promise(); + this.context.print.success('S3 bucket successfully created'); + return bucketName; + } else if (throwIfExists) { + throw new Error(`Bucket ${bucketName} already exists`); + } + } + + async getAllObjectKeys(bucketName, continuationToken = null) { + const result = await pagedAWSCall( + async (param: $TSAny, nextToken?: NextToken) => { + const parmaWithNextToken: ListObjectsV2Request = nextToken ? { ...param, ContinuationToken: nextToken } : param; + return await this.s3.listObjectsV2(parmaWithNextToken).promise(); + }, + { + Bucket: bucketName, + }, + (response?: ListObjectsV2Output) => response.Contents?.map(r => ({ Key: r.Key })), + async (response?: ListObjectsV2Output) => (response && response.IsTruncated ? response.NextContinuationToken : undefined), + ); + return result; + } + + public async deleteAllObjects(bucketName): Promise { + const allObjects = await this.getAllObjectKeys(bucketName); + const chunkedResult = _.chunk(allObjects, 1000); + for (let chunk of chunkedResult) { + await this.s3 + .deleteObjects({ + Bucket: bucketName, + Delete: { + Objects: chunk, + }, + }) + .promise(); + } + } + + public async deleteS3Bucket(bucketName) { + if (await this.ifBucketExists(bucketName)) { + await this.deleteAllObjects(bucketName); + await this.s3.deleteBucket({ Bucket: bucketName }).promise(); + } + } + + public async ifBucketExists(bucketName: string) { + try { + await this.s3 + .headBucket({ + Bucket: bucketName, + }) + .promise(); + return true; + } catch (e) { + if (e.statusCode === 404) { + return false; + } + throw e; + } + } +} diff --git a/packages/amplify-provider-awscloudformation/src/aws-utils/paged-call.ts b/packages/amplify-provider-awscloudformation/src/aws-utils/paged-call.ts new file mode 100644 index 00000000000..d9f24097e47 --- /dev/null +++ b/packages/amplify-provider-awscloudformation/src/aws-utils/paged-call.ts @@ -0,0 +1,27 @@ +import assert from 'assert'; +import { $TSObject } from 'amplify-cli-core'; + +export const pagedAWSCall = async ( + action: (params: $TSObject, nextToken?: TNextToken) => Promise, + params: $TSObject, + accessor: (result?: TAPIResult) => TData[], + getNextToken: (serviceResponse: TAPIResult, result: TData[]) => Promise, +): Promise => { + assert(action, 'missing argument: action'); + assert(accessor, 'missing argument: accessor'); + assert(getNextToken, 'missing argument getNextToken'); + + let result: TData[] = []; + let response: TAPIResult; + let nextToken = undefined; + do { + response = await action(params, nextToken); + + if (response && accessor(response)) { + result = result.concat(accessor(response)); + } + nextToken = response ? await getNextToken(response, result) : false; + } while (!!nextToken); + + return result; +}; diff --git a/packages/amplify-provider-awscloudformation/src/delete-env.js b/packages/amplify-provider-awscloudformation/src/delete-env.js index c6475567616..877ae3931fa 100644 --- a/packages/amplify-provider-awscloudformation/src/delete-env.js +++ b/packages/amplify-provider-awscloudformation/src/delete-env.js @@ -2,7 +2,7 @@ const fs = require('fs-extra'); const path = require('path'); const Cloudformation = require('./aws-utils/aws-cfn'); -const S3 = require('./aws-utils/aws-s3'); +const { S3 } = require('./aws-utils/aws-s3'); const { loadConfigurationForEnv } = require('./configuration-manager'); const { deleteEnv } = require('./amplify-service-manager'); const { S3BackendZipFileName, ProviderName } = require('./constants'); @@ -12,7 +12,7 @@ async function run(context, envName, deleteS3) { const awsConfig = await loadConfigurationForEnv(context, envName); const cfn = await new Cloudformation(context, null, awsConfig); if (deleteS3) { - const s3 = await new S3(context, {}); + const s3 = await S3.getInstance(context, {}); const projectDetails = context.amplify.getProjectDetails(); const projectBucket = projectDetails.teamProviderInfo[envName][ProviderName].DeploymentBucketName; if (await s3.ifBucketExists(projectBucket)) { diff --git a/packages/amplify-provider-awscloudformation/src/initialize-env.js b/packages/amplify-provider-awscloudformation/src/initialize-env.js index 7804f3f75e7..af5b9a81ad0 100644 --- a/packages/amplify-provider-awscloudformation/src/initialize-env.js +++ b/packages/amplify-provider-awscloudformation/src/initialize-env.js @@ -3,7 +3,7 @@ const path = require('path'); const glob = require('glob'); const { PathConstants, stateManager } = require('amplify-cli-core'); const Cloudformation = require('./aws-utils/aws-cfn'); -const S3 = require('./aws-utils/aws-s3'); +const { S3 } = require('./aws-utils/aws-s3'); const { downloadZip, extractZip } = require('./zip-util'); const { S3BackendZipFileName } = require('./constants'); @@ -17,7 +17,7 @@ function run(context, providerMetadata) { const currentCloudBackendDir = context.amplify.pathManager.getCurrentCloudBackendDirPath(); const backendDir = context.amplify.pathManager.getBackendDirPath(); - return new S3(context) + return S3.getInstance(context) .then(s3 => downloadZip(s3, tempDir, S3BackendZipFileName).then(file => extractZip(tempDir, file).then(unzippeddir => { diff --git a/packages/amplify-provider-awscloudformation/src/initializer.js b/packages/amplify-provider-awscloudformation/src/initializer.js index b938c055a0f..07da5d31bc1 100644 --- a/packages/amplify-provider-awscloudformation/src/initializer.js +++ b/packages/amplify-provider-awscloudformation/src/initializer.js @@ -7,7 +7,7 @@ const fs = require('fs-extra'); const ora = require('ora'); const sequential = require('promise-sequential'); const Cloudformation = require('./aws-utils/aws-cfn'); -const S3 = require('./aws-utils/aws-s3'); +const { S3 } = require('./aws-utils/aws-s3'); const constants = require('./constants'); const configurationManager = require('./configuration-manager'); const amplifyServiceManager = require('./amplify-service-manager'); @@ -163,7 +163,7 @@ function storeCurrentCloudBackend(context) { .run(currentCloudBackendDir, zipFilePath, undefined, cliJSONFiles) .then(result => { const s3Key = `${result.zipFilename}`; - return new S3(context).then(s3 => { + return S3.getInstance(context).then(s3 => { const s3Params = { Body: fs.createReadStream(result.zipFilePath), Key: s3Key, @@ -178,7 +178,7 @@ function storeCurrentCloudBackend(context) { } function storeArtifactsForAmplifyService(context) { - return new S3(context).then(async s3 => { + return S3.getInstance(context).then(async s3 => { const currentCloudBackendDir = context.amplify.pathManager.getCurrentCloudBackendDirPath(); const amplifyMetaFilePath = path.join(currentCloudBackendDir, 'amplify-meta.json'); const backendConfigFilePath = path.join(currentCloudBackendDir, 'backend-config.json'); diff --git a/packages/amplify-provider-awscloudformation/src/push-resources.js b/packages/amplify-provider-awscloudformation/src/push-resources.js index baf51df35e3..e82dc6a7fd9 100644 --- a/packages/amplify-provider-awscloudformation/src/push-resources.js +++ b/packages/amplify-provider-awscloudformation/src/push-resources.js @@ -5,7 +5,7 @@ const cfnLint = require('cfn-lint'); const glob = require('glob'); const { pathManager, PathConstants } = require('amplify-cli-core'); const ora = require('ora'); -const S3 = require('./aws-utils/aws-s3'); +const { S3 } = require('./aws-utils/aws-s3'); const Cloudformation = require('./aws-utils/aws-cfn'); const providerName = require('./constants').ProviderName; const { buildResource } = require('./build-resources'); @@ -193,7 +193,7 @@ function storeCurrentCloudBackend(context) { .run(currentCloudBackendDir, zipFilePath, undefined, cliJSONFiles) .then(result => { const s3Key = `${result.zipFilename}`; - return new S3(context).then(s3 => { + return S3.getInstance(context).then(s3 => { const s3Params = { Body: fs.createReadStream(result.zipFilePath), Key: s3Key, @@ -237,7 +237,7 @@ function packageResources(context, resources) { .then(result => { // Upload zip file to S3 s3Key = `amplify-builds/${result.zipFilename}`; - return new S3(context).then(s3 => { + return S3.getInstance(context).then(s3 => { const s3Params = { Body: fs.createReadStream(result.zipFilePath), Key: s3Key, @@ -404,7 +404,7 @@ function updateS3Templates(context, resourcesToBeUpdated, amplifyMeta) { function uploadTemplateToS3(context, resourceDir, cfnFile, category, resourceName, amplifyMeta) { const filePath = path.normalize(path.join(resourceDir, cfnFile)); - return new S3(context) + return S3.getInstance(context) .then(s3 => { const s3Params = { Body: fs.createReadStream(filePath), diff --git a/packages/amplify-provider-awscloudformation/src/upload-appsync-files.js b/packages/amplify-provider-awscloudformation/src/upload-appsync-files.js index 3ac381431a7..aa3ab43d1ae 100644 --- a/packages/amplify-provider-awscloudformation/src/upload-appsync-files.js +++ b/packages/amplify-provider-awscloudformation/src/upload-appsync-files.js @@ -3,11 +3,12 @@ const fsext = require('fs-extra'); const path = require('path'); const TransformPackage = require('graphql-transformer-core'); -const S3 = require('./aws-utils/aws-s3'); +const { S3 } = require('./aws-utils/aws-s3'); const ROOT_APPSYNC_S3_KEY = 'amplify-appsync-files'; const providerName = require('./constants').ProviderName; const { hashElement } = require('folder-hash'); +const ora = require('ora'); const PARAM_FILE_NAME = 'parameters.json'; const CF_FILE_NAME = 'cloudformation-template.json'; @@ -182,20 +183,24 @@ async function uploadAppSyncFiles(context, resourcesToUpdate, allResources, opti writeUpdatedParametersJson(resource, deploymentRootKey); // Upload build/* to S3. - const s3Client = await new S3(context); + const s3Client = await S3.getInstance(context); if (!fs.existsSync(resourceBuildDir)) { return; } + const spinner = new ora('Uploading files...'); await TransformPackage.uploadAPIProject({ directory: resourceBuildDir, upload: async blob => { const { Key, Body } = blob; const fullKey = `${deploymentRootKey}/${Key}`; - return await s3Client.uploadFile({ - Key: fullKey, - Body, - }); + return await s3Client.uploadFile( + { + Key: fullKey, + Body, + }, + spinner, + ); }, }); } else if (allApiResources.length > 0) { diff --git a/packages/amplify-provider-awscloudformation/tsconfig.json b/packages/amplify-provider-awscloudformation/tsconfig.json index bc2d590a84a..fb86a1c33c2 100644 --- a/packages/amplify-provider-awscloudformation/tsconfig.json +++ b/packages/amplify-provider-awscloudformation/tsconfig.json @@ -4,7 +4,8 @@ "outDir": "lib", "rootDir": "src", "strict": false, // TODO enable - "allowJs": true + "allowJs": true, + "checkJs": false // TODO enable till we move everything to TS }, "exclude": [ "lib",